From 1c50d4a198eb504f2ccac9827e3272d1264badb3 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Fri, 20 Feb 2026 10:32:54 +0530 Subject: [PATCH 01/10] fix: #225 Oversized single battery notification icon --- .../essentials/services/BatteryNotificationService.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/sameerasw/essentials/services/BatteryNotificationService.kt b/app/src/main/java/com/sameerasw/essentials/services/BatteryNotificationService.kt index 0b1d0bbfe..24b2ca6a0 100644 --- a/app/src/main/java/com/sameerasw/essentials/services/BatteryNotificationService.kt +++ b/app/src/main/java/com/sameerasw/essentials/services/BatteryNotificationService.kt @@ -161,12 +161,19 @@ class BatteryNotificationService : Service() { private fun createCompositeBitmap(items: List): Bitmap { val itemSize = 256 val spacing = 48 - val totalWidth = items.size * itemSize + (items.size - 1) * spacing + + val actualContentWidth = items.size * itemSize + (items.size - 1).coerceAtLeast(0) * spacing + + val minWideItems = 3 + val minWideWidth = minWideItems * itemSize + (minWideItems - 1) * spacing + val totalWidth = actualContentWidth.coerceAtLeast(minWideWidth) val totalHeight = itemSize val composite = Bitmap.createBitmap(totalWidth, totalHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(composite) + val startX = (totalWidth - actualContentWidth) / 2f + val accentColor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { getColor(android.R.color.system_accent1_100) } else { @@ -189,7 +196,7 @@ class BatteryNotificationService : Service() { item.statusIconRes?.let { ContextCompat.getDrawable(this, it) }, itemSize, itemSize ) - canvas.drawBitmap(itemBitmap, (index * (itemSize + spacing)).toFloat(), 0f, null) + canvas.drawBitmap(itemBitmap, startX + (index * (itemSize + spacing)).toFloat(), 0f, null) } return composite From 077acd851cf598b80115bed2b94a3436f29d96c7 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 06:24:41 +0530 Subject: [PATCH 02/10] feat: Applied standard styling across the app, removed toolbar styling --- .../essentials/AppUpdatesActivity.kt | 2 +- .../com/sameerasw/essentials/MainActivity.kt | 4 +- .../ui/activities/AppFreezingActivity.kt | 7 +- .../activities/FlashlightIntensityActivity.kt | 6 +- .../activities/PrivateDnsSettingsActivity.kt | 8 +- .../ui/components/DIYFloatingToolbar.kt | 174 ++++++------------ .../ui/components/FavoriteCarousel.kt | 4 +- .../ui/components/ReusableTopAppBar.kt | 31 ++-- .../ui/components/cards/TrackedRepoCard.kt | 2 +- .../pickers/EdgeLightingStylePicker.kt | 2 +- .../components/sheets/AddRepoBottomSheet.kt | 6 +- .../components/sheets/BugReportBottomSheet.kt | 14 +- .../sheets/DeviceEffectsSettingsSheet.kt | 4 +- .../sheets/DimWallpaperSettingsSheet.kt | 4 +- .../sheets/FeatureHelpBottomSheet.kt | 4 +- .../components/sheets/NewAutomationSheet.kt | 2 +- .../sheets/SoundModeSettingsSheet.kt | 4 +- .../ui/components/sheets/UpdateBottomSheet.kt | 8 +- .../essentials/ui/composables/DIYScreen.kt | 2 +- .../essentials/ui/composables/FreezeGridUI.kt | 11 +- .../ui/composables/SetupFeatures.kt | 4 +- .../configs/LocationReachedSettingsUI.kt | 26 +-- .../essentials/ui/ime/EmojiPicker.kt | 2 +- .../com/sameerasw/essentials/ui/theme/Type.kt | 96 +++++++++- 24 files changed, 223 insertions(+), 204 deletions(-) diff --git a/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt b/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt index c968b0396..ba28d8ec6 100644 --- a/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt @@ -323,7 +323,7 @@ class AppUpdatesActivity : FragmentActivity() { modifier = Modifier.fillMaxSize(), contentPadding = androidx.compose.foundation.layout.PaddingValues( top = innerPadding.calculateTopPadding() + 16.dp, - bottom = innerPadding.calculateBottomPadding() + 100.dp, + bottom = 150.dp, start = 16.dp, end = 16.dp ), diff --git a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt index 66486d514..675025b34 100644 --- a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt @@ -557,7 +557,7 @@ class MainActivity : FragmentActivity() { modifier = Modifier.fillMaxSize(), contentPadding = androidx.compose.foundation.layout.PaddingValues( top = innerPadding.calculateTopPadding() + 16.dp, - bottom = innerPadding.calculateBottomPadding() + 88.dp, // Extra padding for FAB + bottom = 150.dp, start = 16.dp, end = 16.dp ), @@ -776,7 +776,7 @@ class MainActivity : FragmentActivity() { modifier = Modifier .align(Alignment.BottomEnd) .padding( - bottom = innerPadding.calculateBottomPadding() + 32.dp, + bottom = 150.dp, end = 32.dp ), containerColor = MaterialTheme.colorScheme.primaryContainer, diff --git a/app/src/main/java/com/sameerasw/essentials/ui/activities/AppFreezingActivity.kt b/app/src/main/java/com/sameerasw/essentials/ui/activities/AppFreezingActivity.kt index 859c034d0..58ac2a406 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/activities/AppFreezingActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/activities/AppFreezingActivity.kt @@ -195,14 +195,14 @@ class AppFreezingActivity : ComponentActivity() { Column( modifier = Modifier .fillMaxSize() - .padding(32.dp), + .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Icon( painter = painterResource(id = R.drawable.rounded_mode_cool_24), contentDescription = null, - modifier = Modifier.size(64.dp), + modifier = Modifier.size(24.dp), tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f) ) Spacer(modifier = Modifier.height(16.dp)) @@ -216,7 +216,7 @@ class AppFreezingActivity : ComponentActivity() { } else { RoundedCardContainer( modifier = Modifier - .padding(24.dp) + .padding(16.dp) ) { LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 88.dp), @@ -334,7 +334,6 @@ fun AppGridItem( Text( text = app.appName, style = MaterialTheme.typography.labelSmall, - fontSize = 11.sp, textAlign = TextAlign.Center, maxLines = 1, overflow = TextOverflow.Ellipsis, diff --git a/app/src/main/java/com/sameerasw/essentials/ui/activities/FlashlightIntensityActivity.kt b/app/src/main/java/com/sameerasw/essentials/ui/activities/FlashlightIntensityActivity.kt index a460b45ee..21c4e652e 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/activities/FlashlightIntensityActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/activities/FlashlightIntensityActivity.kt @@ -139,7 +139,7 @@ fun FlashlightIntensityOverlay(onDismiss: () -> Unit) { ) { Card( modifier = Modifier - .padding(24.dp) + .padding(16.dp) .fillMaxWidth() .clickable( interactionSource = remember { MutableInteractionSource() }, @@ -152,7 +152,7 @@ fun FlashlightIntensityOverlay(onDismiss: () -> Unit) { ) ) { Column( - modifier = Modifier.padding(24.dp), + modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(16.dp) ) { @@ -160,7 +160,7 @@ fun FlashlightIntensityOverlay(onDismiss: () -> Unit) { painter = painterResource(id = R.drawable.rounded_flashlight_on_24), contentDescription = null, tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(48.dp) + modifier = Modifier.size(24.dp) ) Text( diff --git a/app/src/main/java/com/sameerasw/essentials/ui/activities/PrivateDnsSettingsActivity.kt b/app/src/main/java/com/sameerasw/essentials/ui/activities/PrivateDnsSettingsActivity.kt index 5c6494f96..8f2a00957 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/activities/PrivateDnsSettingsActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/activities/PrivateDnsSettingsActivity.kt @@ -116,7 +116,7 @@ fun PrivateDnsSettingsOverlay(onDismiss: () -> Unit) { painter = painterResource(id = R.drawable.router_24px), contentDescription = null, tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) Text( text = stringResource(R.string.tile_private_dns), @@ -212,14 +212,14 @@ fun PrivateDnsSettingsOverlay(onDismiss: () -> Unit) { Row( modifier = Modifier .fillMaxWidth() - .padding(bottom = 24.dp, top = 12.dp), + .padding(bottom = 16.dp, top = 8.dp), horizontalArrangement = Arrangement.spacedBy(12.dp) ) { OutlinedButton( onClick = onDismiss, modifier = Modifier .weight(1f) - .height(56.dp), + .height(48.dp), shape = RoundedCornerShape(24.dp) ) { Text(stringResource(R.string.action_cancel)) @@ -248,7 +248,7 @@ fun PrivateDnsSettingsOverlay(onDismiss: () -> Unit) { }, modifier = Modifier .weight(1f) - .height(56.dp), + .height(48.dp), shape = RoundedCornerShape(24.dp) ) { Text(stringResource(R.string.action_save)) diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt index 20ab819af..ff6eb58ae 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt @@ -1,15 +1,17 @@ package com.sameerasw.essentials.ui.components -import androidx.compose.animation.core.Spring import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingToolbarDefaults @@ -19,22 +21,19 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf 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.graphics.graphicsLayer import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.sameerasw.essentials.domain.DIYTabs -import kotlinx.coroutines.delay @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -46,52 +45,16 @@ fun DIYFloatingToolbar( scrollBehavior: FloatingToolbarScrollBehavior, badges: Map = emptyMap() ) { + // Persistent visibility var expanded by remember { mutableStateOf(true) } - var interactionCount by remember { mutableStateOf(0) } - - // Track which tab was just selected for bump animation - var bumpingTab by remember { mutableIntStateOf(-1) } - var bumpKey by remember { mutableIntStateOf(0) } - - // Auto-collapse after 5 seconds - LaunchedEffect(expanded, interactionCount, currentPage) { - if (expanded) { - delay(5000) - expanded = false - } - } - - // Reset bump animation after delay - LaunchedEffect(bumpKey) { - if (bumpingTab >= 0) { - delay(200) - bumpingTab = -1 - } - } - - // Expand when the page changes (e.g., via swipe) - LaunchedEffect(currentPage) { - if (!expanded) expanded = true - } - - // Animated values for bouncy feel - val toolbarScale by animateFloatAsState( - targetValue = if (expanded) 1f else 0.9f, - animationSpec = spring( - dampingRatio = Spring.DampingRatioMediumBouncy, - stiffness = Spring.StiffnessMediumLow - ), - label = "toolbar_scale" - ) HorizontalFloatingToolbar( modifier = modifier - .graphicsLayer { - scaleX = toolbarScale - scaleY = toolbarScale - }, + .windowInsetsPadding( + androidx.compose.foundation.layout.WindowInsets.navigationBars + ), expanded = expanded, - scrollBehavior = scrollBehavior, +// scrollBehavior = scrollBehavior, colors = FloatingToolbarDefaults.vibrantFloatingToolbarColors( toolbarContentColor = MaterialTheme.colorScheme.onSurface, toolbarContainerColor = MaterialTheme.colorScheme.primary, @@ -100,47 +63,25 @@ fun DIYFloatingToolbar( // FIXED ORDER LOOP to prevent shifting tabs.forEachIndexed { index, tab -> val isSelected = currentPage == index - val isBumping = bumpingTab == index - - // Animate scale for non-selected tabs when collapsing/expanding - val itemScale by animateFloatAsState( - targetValue = when { - isBumping -> 1.28f // Subtle bump animation when selected - isSelected -> 1.2f - expanded -> 1.2f - else -> 0f // Scale down to 0 when collapsed - }, - animationSpec = spring( - dampingRatio = if (isBumping) Spring.DampingRatioMediumBouncy else Spring.DampingRatioLowBouncy, - stiffness = if (isBumping) Spring.StiffnessHigh else Spring.StiffnessLow - ), - label = "item_scale_$index" - ) - - // Animate alpha for smooth fade - val itemAlpha by animateFloatAsState( - targetValue = if (expanded || isSelected) 1f else 0f, - animationSpec = tween(durationMillis = 200), - label = "item_alpha_$index" - ) // Animate width for spacing val itemWidth by animateDpAsState( targetValue = if (expanded || isSelected) 48.dp else 0.dp, - animationSpec = spring( - dampingRatio = Spring.DampingRatioLowBouncy, - stiffness = Spring.StiffnessLow - ), + animationSpec = tween(durationMillis = 300), label = "item_width_$index" ) + // Animate label width for active tab + val labelWidth by animateDpAsState( + targetValue = if (isSelected) 80.dp else 0.dp, + animationSpec = tween(durationMillis = 300), + label = "label_width_$index" + ) + // Animate spacer width val spacerWidth by animateDpAsState( - targetValue = if (expanded && index < tabs.size - 1) 16.dp else 0.dp, - animationSpec = spring( - dampingRatio = Spring.DampingRatioNoBouncy, - stiffness = Spring.StiffnessMediumLow - ), + targetValue = if (index < tabs.size - 1) 8.dp else 0.dp, + animationSpec = tween(durationMillis = 300), label = "spacer_width_$index" ) @@ -148,23 +89,11 @@ fun DIYFloatingToolbar( if (itemWidth > 0.dp || isSelected) { IconButton( onClick = { - interactionCount++ - if (!expanded) { - expanded = true - } else { - bumpingTab = index - bumpKey++ - onTabSelected(index) - } + onTabSelected(index) }, modifier = Modifier - .width(itemWidth) - .height(48.dp) - .graphicsLayer { - scaleX = itemScale - scaleY = itemScale - alpha = itemAlpha - }, + .width(itemWidth + labelWidth) + .height(48.dp), colors = if (isSelected) { IconButtonDefaults.filledIconButtonColors( contentColor = MaterialTheme.colorScheme.primary, @@ -177,28 +106,43 @@ fun DIYFloatingToolbar( ) } ) { - Box { - Icon( - painter = painterResource(id = tab.iconRes), - contentDescription = stringResource(id = tab.title), - tint = if (isSelected) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.background - }, - modifier = Modifier.size(24.dp) - ) - if (badges[tab] == true) { - androidx.compose.foundation.Canvas( - modifier = Modifier - .size(8.dp) - .align(Alignment.TopEnd) - ) { - drawCircle( - color = if (isSelected) Color.Red else Color.Red, // Always red for now - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier.padding(horizontal = 8.dp) + ) { + Box { + Icon( + painter = painterResource(id = tab.iconRes), + contentDescription = stringResource(id = tab.title), + tint = if (isSelected) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.background + }, + modifier = Modifier.size(24.dp) + ) + if (badges[tab] == true) { + androidx.compose.foundation.Canvas( + modifier = Modifier + .size(8.dp) + .align(Alignment.TopEnd) + ) { + drawCircle( + color = Color.Red, + ) + } } } + if (isSelected) { + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(id = tab.title), + style = MaterialTheme.typography.labelLarge, + maxLines = 1, + color = MaterialTheme.colorScheme.primary + ) + } } } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/FavoriteCarousel.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/FavoriteCarousel.kt index bdff55bed..d939e015c 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/FavoriteCarousel.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/FavoriteCarousel.kt @@ -159,7 +159,7 @@ fun FavoriteCarousel( ) { Box( modifier = Modifier - .size(48.dp) + .size(40.dp) .background( color = ColorUtil.getPastelColorFor(resolvedTitle), shape = CircleShape @@ -169,7 +169,7 @@ fun FavoriteCarousel( Icon( painter = painterResource(id = feature.iconRes), contentDescription = resolvedTitle, - modifier = Modifier.size(28.dp), + modifier = Modifier.size(24.dp), tint = ColorUtil.getVibrantColorFor(resolvedTitle) ) } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt index c153b4bb6..4e9ffdcdc 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt @@ -166,13 +166,12 @@ fun ReusableTopAppBar( }, colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright - ), - modifier = Modifier.size(48.dp) + ) ) { Icon( painter = painterResource(id = backIconRes), contentDescription = stringResource(R.string.action_back), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } @@ -190,14 +189,13 @@ fun ReusableTopAppBar( }, colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright - ), - modifier = Modifier.size(48.dp) + ) ) { Box { Icon( painter = painterResource(id = helpIconRes), contentDescription = stringResource(helpContentDescription), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) if (hasHelpBadge) { Box( @@ -224,14 +222,13 @@ fun ReusableTopAppBar( }, colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright - ), - modifier = Modifier.size(48.dp) + ) ) { Box { Icon( painter = painterResource(id = R.drawable.rounded_mobile_arrow_down_24), contentDescription = stringResource(R.string.update_available_title), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) // Red dot Box( @@ -268,8 +265,7 @@ fun ReusableTopAppBar( }, colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright - ), - modifier = Modifier.size(48.dp) + ) ) { if (gitHubUser != null) { AsyncImage( @@ -277,14 +273,14 @@ fun ReusableTopAppBar( contentDescription = stringResource(R.string.action_profile), contentScale = ContentScale.Crop, modifier = Modifier - .size(32.dp) + .size(24.dp) .clip(CircleShape) ) } else { Icon( painter = painterResource(id = R.drawable.brand_github), contentDescription = stringResource(R.string.action_sign_in_github), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } @@ -325,13 +321,12 @@ fun ReusableTopAppBar( }, colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright - ), - modifier = Modifier.size(48.dp) + ) ) { Icon( painter = painterResource(id = R.drawable.rounded_settings_heart_24), contentDescription = stringResource(R.string.content_desc_settings), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } @@ -354,8 +349,8 @@ fun ReusableTopAppBar( containerColor = containerColor ), modifier = Modifier.padding(horizontal = 8.dp), - expandedHeight = if (subtitle != null) 200.dp else 160.dp, - collapsedHeight = 64.dp, + expandedHeight = if (subtitle != null) 152.dp else 120.dp, + collapsedHeight = TopAppBarDefaults.LargeAppBarCollapsedHeight, title = titleContent, navigationIcon = navigationIconContent, actions = actionsContent, diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/cards/TrackedRepoCard.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/cards/TrackedRepoCard.kt index d76e6a984..2b21ec5fa 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/cards/TrackedRepoCard.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/cards/TrackedRepoCard.kt @@ -210,7 +210,7 @@ fun TrackedRepoCard( ) { CircularWavyProgressIndicator( progress = { downloadProgress }, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } else if (repo.isUpdateAvailable || repo.mappedPackageName == null) { diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/pickers/EdgeLightingStylePicker.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/pickers/EdgeLightingStylePicker.kt index a38df35b4..53c446791 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/pickers/EdgeLightingStylePicker.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/pickers/EdgeLightingStylePicker.kt @@ -74,7 +74,7 @@ fun NotificationLightingStylePicker( Icon( painter = painterResource(id = icons[index]), contentDescription = style.name, - modifier = Modifier.size(48.dp) + modifier = Modifier.size(24.dp) ) } } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/AddRepoBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/AddRepoBottomSheet.kt index b9379703b..ced2c4211 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/AddRepoBottomSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/AddRepoBottomSheet.kt @@ -289,7 +289,7 @@ fun AddRepoBottomSheet( Icon( painter = painterResource(id = R.drawable.round_star_24), contentDescription = null, - modifier = Modifier.size(16.dp) + modifier = Modifier.size(24.dp) ) Text( text = stringResource( @@ -312,7 +312,7 @@ fun AddRepoBottomSheet( Icon( painterResource(id = R.drawable.rounded_mobile_text_2_24), null, - Modifier.size(18.dp) + Modifier.size(24.dp) ) Spacer(Modifier.width(8.dp)) Text(stringResource(R.string.action_view_readme)) @@ -498,7 +498,7 @@ fun AddRepoBottomSheet( bitmap = selectedApp!!.icon, contentDescription = null, modifier = Modifier - .size(32.dp) + .size(24.dp) .clip(CircleShape) ) Column { diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/BugReportBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/BugReportBottomSheet.kt index 6fb6e2d04..629fef0d6 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/BugReportBottomSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/BugReportBottomSheet.kt @@ -113,8 +113,8 @@ fun BugReportBottomSheet( ) { Column( modifier = Modifier - .padding(horizontal = 24.dp) - .padding(bottom = 32.dp) + .padding(horizontal = 16.dp) + .padding(bottom = 24.dp) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally @@ -129,7 +129,7 @@ fun BugReportBottomSheet( Column( modifier = Modifier .background(MaterialTheme.colorScheme.surfaceBright) - .padding(24.dp) + .padding(16.dp) .fillMaxWidth() ) { Text( @@ -160,7 +160,7 @@ fun BugReportBottomSheet( modifier = Modifier .fillMaxWidth() .clickable { isRawReportExpanded = !isRawReportExpanded } - .padding(vertical = 16.dp, horizontal = 24.dp), + .padding(16.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { @@ -236,7 +236,7 @@ fun BugReportBottomSheet( Icon( painter = painterResource(R.drawable.brand_github), contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text(stringResource(R.string.action_report_github)) @@ -269,7 +269,7 @@ fun BugReportBottomSheet( Icon( painter = painterResource(R.drawable.rounded_mail_24), contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text(stringResource(R.string.action_report_email)) @@ -293,7 +293,7 @@ fun BugReportBottomSheet( Icon( painter = painterResource(R.drawable.rounded_content_copy_24), contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text(stringResource(R.string.action_copy_clipboard)) diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DeviceEffectsSettingsSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DeviceEffectsSettingsSheet.kt index 7903f4379..deaea3e76 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DeviceEffectsSettingsSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DeviceEffectsSettingsSheet.kt @@ -66,9 +66,9 @@ fun DeviceEffectsSettingsSheet( ) { Column( modifier = Modifier - .padding(24.dp) + .padding(16.dp) .fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(24.dp) + verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text( text = stringResource(R.string.diy_action_device_effects), diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DimWallpaperSettingsSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DimWallpaperSettingsSheet.kt index 21ac95a85..3c5e9accd 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DimWallpaperSettingsSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/DimWallpaperSettingsSheet.kt @@ -59,9 +59,9 @@ fun DimWallpaperSettingsSheet( ) { Column( modifier = Modifier - .padding(24.dp) + .padding(16.dp) .fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(24.dp) + verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text( text = stringResource(R.string.diy_action_dim_wallpaper), diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/FeatureHelpBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/FeatureHelpBottomSheet.kt index 11ed870f0..24b044ecf 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/FeatureHelpBottomSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/FeatureHelpBottomSheet.kt @@ -62,7 +62,7 @@ fun FeatureHelpBottomSheet( ) { Box( modifier = Modifier - .size(48.dp) + .size(40.dp) .background( color = ColorUtil.getPastelColorFor(stringResource(feature.title)), shape = CircleShape @@ -72,7 +72,7 @@ fun FeatureHelpBottomSheet( Icon( painter = painterResource(id = feature.iconRes), contentDescription = null, - modifier = Modifier.size(32.dp), + modifier = Modifier.size(24.dp), tint = ColorUtil.getVibrantColorFor(stringResource(feature.title)) ) } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/NewAutomationSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/NewAutomationSheet.kt index c285b7fbd..ea754ab10 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/NewAutomationSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/NewAutomationSheet.kt @@ -129,7 +129,7 @@ private fun AutomationTypeOption( Icon( painter = painterResource(id = iconRes), contentDescription = null, - modifier = Modifier.size(32.dp), + modifier = Modifier.size(24.dp), tint = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.width(16.dp)) diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/SoundModeSettingsSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/SoundModeSettingsSheet.kt index 015dae4e3..a66329882 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/SoundModeSettingsSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/SoundModeSettingsSheet.kt @@ -41,9 +41,9 @@ fun SoundModeSettingsSheet( ) { Column( modifier = Modifier - .padding(24.dp) + .padding(16.dp) .fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(24.dp) + verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text( text = stringResource(R.string.diy_action_sound_mode), diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/UpdateBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/UpdateBottomSheet.kt index 7e6647d61..d7ab8a7c1 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/UpdateBottomSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/sheets/UpdateBottomSheet.kt @@ -80,7 +80,7 @@ fun UpdateBottomSheet( Icon( painter = painterResource(id = if (updateInfo.isUpdateAvailable) R.drawable.rounded_mobile_arrow_down_24 else R.drawable.rounded_mobile_check_24), contentDescription = null, - modifier = Modifier.size(64.dp), + modifier = Modifier.size(24.dp), tint = if (updateInfo.isUpdateAvailable) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary ) @@ -113,7 +113,7 @@ fun UpdateBottomSheet( painter = painterResource(id = R.drawable.rounded_mobile_code_24), contentDescription = null, tint = MaterialTheme.colorScheme.error, - modifier = Modifier.size(20.dp) + modifier = Modifier.size(24.dp) ) Text( text = stringResource(R.string.warning_pre_release), @@ -167,7 +167,7 @@ fun UpdateBottomSheet( Icon( painter = painterResource(id = R.drawable.brand_github), contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text(stringResource(R.string.action_view_on_github)) @@ -187,7 +187,7 @@ fun UpdateBottomSheet( } } - Spacer(modifier = Modifier.height(32.dp)) + Spacer(modifier = Modifier.height(16.dp)) } } } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/DIYScreen.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/DIYScreen.kt index 6f3c2b45e..3a8ab2cbd 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/composables/DIYScreen.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/DIYScreen.kt @@ -75,7 +75,7 @@ fun DIYScreen( LazyColumn( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = PaddingValues(bottom = 80.dp) + contentPadding = PaddingValues(bottom = 150.dp) ) { if (enabledAutomations.isNotEmpty()) { item { diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/FreezeGridUI.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/FreezeGridUI.kt index 5dcd47370..d60ff16e9 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/composables/FreezeGridUI.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/FreezeGridUI.kt @@ -123,14 +123,14 @@ fun FreezeGridUI( Column( modifier = Modifier .fillMaxSize() - .padding(18.dp), + .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Icon( painter = painterResource(id = R.drawable.rounded_mode_cool_24), contentDescription = null, - modifier = Modifier.size(64.dp), + modifier = Modifier.size(24.dp), tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f) ) Spacer(modifier = Modifier.height(16.dp)) @@ -145,14 +145,14 @@ fun FreezeGridUI( RoundedCardContainer( modifier = Modifier .padding(horizontal = 16.dp) - .padding(top = 24.dp), + .padding(top = 16.dp), ) { LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 88.dp), state = gridState, modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues( - bottom = contentPadding.calculateBottomPadding() + 88.dp, + bottom = 150.dp, top = 0.dp ), horizontalArrangement = Arrangement.spacedBy(2.dp), @@ -184,7 +184,7 @@ fun FreezeGridUI( Box( modifier = Modifier .align(Alignment.BottomEnd) - .padding(bottom = contentPadding.calculateBottomPadding() + 16.dp, end = 16.dp) + .padding(bottom = 150.dp, end = 16.dp) ) { ExpandableFreezeFab( onUnfreezeAll = { viewModel.unfreezeAllApps(context) }, @@ -274,7 +274,6 @@ fun AppGridItem( Text( text = app.appName, style = MaterialTheme.typography.labelSmall, - fontSize = 11.sp, textAlign = TextAlign.Center, maxLines = 1, overflow = TextOverflow.Ellipsis, diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/SetupFeatures.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/SetupFeatures.kt index 9fda8dabf..d88bfb4e0 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/composables/SetupFeatures.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/SetupFeatures.kt @@ -780,7 +780,7 @@ fun SetupFeatures( .pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) } - .padding(vertical = 24.dp), + .padding(top = 16.dp, bottom = 150.dp), verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.Start ) { @@ -791,7 +791,7 @@ fun SetupFeatures( }, modifier = Modifier .fillMaxWidth() - .padding(24.dp) + .padding(16.dp) .focusRequester(focusRequester) .onFocusChanged { isFocused = it.isFocused }, leadingIcon = { diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/LocationReachedSettingsUI.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/LocationReachedSettingsUI.kt index 6b9698750..26a3549f4 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/LocationReachedSettingsUI.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/LocationReachedSettingsUI.kt @@ -70,7 +70,7 @@ fun LocationReachedSettingsUI( Column( modifier = Modifier .fillMaxWidth() - .padding(24.dp), + .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { LoadingIndicator() @@ -85,16 +85,16 @@ fun LocationReachedSettingsUI( // Destination Set State RoundedCardContainer( modifier = Modifier, - cornerRadius = 24.dp + cornerRadius = 28.dp ) { Column( modifier = Modifier .fillMaxWidth() .background( color = MaterialTheme.colorScheme.surfaceBright, - shape = androidx.compose.foundation.shape.RoundedCornerShape(24.dp) + shape = androidx.compose.foundation.shape.RoundedCornerShape(28.dp) ) - .padding(20.dp), + .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { @@ -164,7 +164,7 @@ fun LocationReachedSettingsUI( Icon( painter = painterResource(id = R.drawable.rounded_my_location_24), contentDescription = null, - modifier = Modifier.size(48.dp), + modifier = Modifier.size(24.dp), tint = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.height(16.dp)) @@ -224,7 +224,7 @@ fun LocationReachedSettingsUI( Icon( painterResource(R.drawable.rounded_map_24), contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text(stringResource(R.string.location_reached_view_map)) @@ -239,7 +239,7 @@ fun LocationReachedSettingsUI( Icon( painterResource(R.drawable.rounded_delete_24), contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text(stringResource(R.string.location_reached_clear)) @@ -251,18 +251,18 @@ fun LocationReachedSettingsUI( // Empty State RoundedCardContainer( modifier = Modifier.fillMaxWidth(), - cornerRadius = 24.dp + cornerRadius = 28.dp ) { Column( modifier = Modifier - .padding(32.dp) + .padding(16.dp) .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Icon( painter = painterResource(id = R.drawable.rounded_add_location_alt_24), contentDescription = null, - modifier = Modifier.size(64.dp), + modifier = Modifier.size(24.dp), tint = MaterialTheme.colorScheme.surfaceVariant ) Spacer(modifier = Modifier.height(16.dp)) @@ -308,7 +308,7 @@ fun LocationReachedSettingsUI( RoundedCardContainer( modifier = Modifier, - cornerRadius = 24.dp + cornerRadius = 28.dp ) { Column( modifier = Modifier @@ -333,9 +333,9 @@ fun LocationReachedSettingsUI( RoundedCardContainer( modifier = Modifier.background( color = MaterialTheme.colorScheme.errorContainer, - shape = androidx.compose.foundation.shape.RoundedCornerShape(24.dp) + shape = androidx.compose.foundation.shape.RoundedCornerShape(28.dp) ), - cornerRadius = 24.dp + cornerRadius = 28.dp ) { IconToggleItem( title = stringResource(R.string.location_reached_fsi_title), diff --git a/app/src/main/java/com/sameerasw/essentials/ui/ime/EmojiPicker.kt b/app/src/main/java/com/sameerasw/essentials/ui/ime/EmojiPicker.kt index bbd620c23..df4b0026c 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/ime/EmojiPicker.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/ime/EmojiPicker.kt @@ -208,7 +208,7 @@ fun EmojiPicker( contentDescription = category.name, tint = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.size(20.dp) + modifier = Modifier.size(24.dp) ) } } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/theme/Type.kt b/app/src/main/java/com/sameerasw/essentials/ui/theme/Type.kt index 54629fdb3..a4102e65d 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/theme/Type.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/theme/Type.kt @@ -15,14 +15,48 @@ val GoogleSansFlex = FontFamily( // Set of Material typography styles to start with, using GoogleSansFlex throughout val Typography = Typography( - bodyLarge = TextStyle( + displayLarge = TextStyle( fontFamily = GoogleSansFlex, fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp - ) - /* Other default text styles to override can also use GoogleSansFlex, for example: + fontSize = 57.sp, + lineHeight = 64.sp, + letterSpacing = (-0.25).sp + ), + displayMedium = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 45.sp, + lineHeight = 52.sp, + letterSpacing = 0.sp + ), + displaySmall = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 36.sp, + lineHeight = 44.sp, + letterSpacing = 0.sp + ), + headlineLarge = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 32.sp, + lineHeight = 40.sp, + letterSpacing = 0.sp + ), + headlineMedium = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 28.sp, + lineHeight = 36.sp, + letterSpacing = 0.sp + ), + headlineSmall = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing = 0.sp + ), titleLarge = TextStyle( fontFamily = GoogleSansFlex, fontWeight = FontWeight.Normal, @@ -30,6 +64,55 @@ val Typography = Typography( lineHeight = 28.sp, letterSpacing = 0.sp ), + titleMedium = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Medium, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.15.sp + ), + titleSmall = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp + ), + bodyLarge = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ), + bodyMedium = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.25.sp + ), + bodySmall = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.4.sp + ), + labelLarge = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp + ), + labelMedium = TextStyle( + fontFamily = GoogleSansFlex, + fontWeight = FontWeight.Medium, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ), labelSmall = TextStyle( fontFamily = GoogleSansFlex, fontWeight = FontWeight.Medium, @@ -37,5 +120,4 @@ val Typography = Typography( lineHeight = 16.sp, letterSpacing = 0.5.sp ) - */ ) \ No newline at end of file From 24b2e506b2884a2129e5fa32ed98884b78c30a5d Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 09:50:58 +0530 Subject: [PATCH 03/10] fix: Top app bar button sizes --- .../com/sameerasw/essentials/AppUpdatesActivity.kt | 8 ++++---- .../sameerasw/essentials/FeatureSettingsActivity.kt | 4 ++-- .../main/java/com/sameerasw/essentials/MainActivity.kt | 8 ++++---- .../java/com/sameerasw/essentials/SettingsActivity.kt | 10 +++++++--- .../essentials/ui/components/ReusableTopAppBar.kt | 3 ++- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt b/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt index ba28d8ec6..782b495e7 100644 --- a/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/AppUpdatesActivity.kt @@ -226,25 +226,25 @@ class AppUpdatesActivity : FragmentActivity() { actions = { androidx.compose.material3.IconButton( onClick = { - HapticUtil.performMediumHaptic(view) + HapticUtil.performVirtualKeyHaptic(view) updatesViewModel.checkForUpdates(context) }, enabled = refreshingRepoIds.isEmpty(), colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright ), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(40.dp) ) { if (refreshingRepoIds.isNotEmpty()) { CircularWavyProgressIndicator( progress = { animatedProgress }, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } else { androidx.compose.material3.Icon( painter = painterResource(id = R.drawable.rounded_refresh_24), contentDescription = stringResource(R.string.action_refresh), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } diff --git a/app/src/main/java/com/sameerasw/essentials/FeatureSettingsActivity.kt b/app/src/main/java/com/sameerasw/essentials/FeatureSettingsActivity.kt index dd5b2bffa..c33c91ccf 100644 --- a/app/src/main/java/com/sameerasw/essentials/FeatureSettingsActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/FeatureSettingsActivity.kt @@ -324,12 +324,12 @@ class FeatureSettingsActivity : FragmentActivity() { colors = androidx.compose.material3.IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright ), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(40.dp) ) { Icon( painter = painterResource(id = R.drawable.rounded_more_vert_24), contentDescription = stringResource(R.string.content_desc_more_options), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) com.sameerasw.essentials.ui.components.menus.SegmentedDropdownMenu( diff --git a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt index 675025b34..b175cf011 100644 --- a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt @@ -420,25 +420,25 @@ class MainActivity : FragmentActivity() { if (currentTab == DIYTabs.APPS) { IconButton( onClick = { - HapticUtil.performMediumHaptic(view) + HapticUtil.performVirtualKeyHaptic(view) updatesViewModel.checkForUpdates(context) }, enabled = refreshingRepoIds.isEmpty(), colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright ), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(40.dp) ) { if (refreshingRepoIds.isNotEmpty()) { CircularWavyProgressIndicator( progress = { animatedProgress }, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } else { Icon( painter = painterResource(id = R.drawable.rounded_refresh_24), contentDescription = stringResource(R.string.action_refresh), - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } diff --git a/app/src/main/java/com/sameerasw/essentials/SettingsActivity.kt b/app/src/main/java/com/sameerasw/essentials/SettingsActivity.kt index 2b70802f5..6100d7dfb 100644 --- a/app/src/main/java/com/sameerasw/essentials/SettingsActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/SettingsActivity.kt @@ -102,6 +102,7 @@ class SettingsActivity : ComponentActivity() { val isPitchBlackThemeEnabled by viewModel.isPitchBlackThemeEnabled EssentialsTheme(pitchBlackTheme = isPitchBlackThemeEnabled) { val context = LocalContext.current + val view = LocalView.current val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) @@ -136,16 +137,19 @@ class SettingsActivity : ComponentActivity() { scrollBehavior = scrollBehavior, actions = { androidx.compose.material3.IconButton( - onClick = { showBugReportSheet = true }, + onClick = { + HapticUtil.performVirtualKeyHaptic(view) + showBugReportSheet = true + }, colors = androidx.compose.material3.IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright ), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(40.dp) ) { Icon( painter = painterResource(id = R.drawable.rounded_bug_report_24), contentDescription = "Report Bug", - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt index 4e9ffdcdc..ea357a01b 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt @@ -265,7 +265,8 @@ fun ReusableTopAppBar( }, colors = IconButtonDefaults.iconButtonColors( containerColor = MaterialTheme.colorScheme.surfaceBright - ) + ), + modifier = Modifier.size(40.dp) ) { if (gitHubUser != null) { AsyncImage( From 6c7d5f0e90c74b6b86e6242d5ec6fd6c468a3ee6 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 15:45:24 +0530 Subject: [PATCH 04/10] fix: Bottom toolbar padding --- app/src/main/java/com/sameerasw/essentials/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt index b175cf011..bd009bb6b 100644 --- a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt @@ -455,7 +455,7 @@ class MainActivity : FragmentActivity() { DIYFloatingToolbar( modifier = Modifier .align(Alignment.BottomCenter) - .offset(y = -ScreenOffset - 12.dp) + .offset(y = -ScreenOffset) .zIndex(1f), currentPage = pagerState.currentPage, tabs = tabs, From 790ec3fb351034824924125e6c83f18566875079 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 16:00:50 +0530 Subject: [PATCH 05/10] feat: Remove horizontal pager --- .../com/sameerasw/essentials/MainActivity.kt | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt index bd009bb6b..6cd9136a9 100644 --- a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt @@ -251,14 +251,13 @@ class MainActivity : FragmentActivity() { val index = tabs.indexOf(defaultTab) if (index != -1) index else 0 } - val pagerState = - rememberPagerState(initialPage = initialPage, pageCount = { tabs.size }) - val scope = rememberCoroutineScope() + + var currentPage by remember { androidx.compose.runtime.mutableIntStateOf(initialPage) } // Gracefully handle tab removal (e.g. disabling Developer Mode) LaunchedEffect(tabs) { - if (pagerState.currentPage >= tabs.size) { - pagerState.scrollToPage(0) + if (currentPage >= tabs.size) { + currentPage = 0 } } val exitAlwaysScrollBehavior = @@ -381,8 +380,8 @@ class MainActivity : FragmentActivity() { .nestedScroll(exitAlwaysScrollBehavior), containerColor = MaterialTheme.colorScheme.surfaceContainer, topBar = { - val currentTab = remember(tabs, pagerState.currentPage) { - tabs.getOrNull(pagerState.currentPage) ?: tabs.firstOrNull() + val currentTab = remember(tabs, currentPage) { + tabs.getOrNull(currentPage) ?: tabs.firstOrNull() ?: DIYTabs.ESSENTIALS } ReusableTopAppBar( @@ -457,25 +456,17 @@ class MainActivity : FragmentActivity() { .align(Alignment.BottomCenter) .offset(y = -ScreenOffset) .zIndex(1f), - currentPage = pagerState.currentPage, + currentPage = currentPage, tabs = tabs, onTabSelected = { index -> HapticUtil.performUIHaptic(view) - scope.launch { - pagerState.animateScrollToPage(index) - } + currentPage = index }, scrollBehavior = exitAlwaysScrollBehavior, badges = mapOf(DIYTabs.APPS to viewModel.hasPendingUpdates.value) ) - HorizontalPager( - state = pagerState, - modifier = Modifier.fillMaxSize(), - verticalAlignment = Alignment.Top, - beyondViewportPageCount = 1 - ) { page -> - when (tabs[page]) { + when (tabs[currentPage]) { DIYTabs.ESSENTIALS -> { SetupFeatures( viewModel = viewModel, @@ -794,7 +785,6 @@ class MainActivity : FragmentActivity() { } } - // Mark app as ready after composing (happens very quickly) LaunchedEffect(Unit) { isAppReady = true @@ -802,7 +792,6 @@ class MainActivity : FragmentActivity() { } } } - } override fun onResume() { super.onResume() From d910b1c10d7aa84ece8d2ef1ba397df5b27fcd94 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 16:40:40 +0530 Subject: [PATCH 06/10] feat: Tab switch animation --- .../com/sameerasw/essentials/MainActivity.kt | 48 ++++++++++++++----- .../ui/components/DIYFloatingToolbar.kt | 19 ++++++-- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt index 6cd9136a9..8221d567b 100644 --- a/app/src/main/java/com/sameerasw/essentials/MainActivity.kt +++ b/app/src/main/java/com/sameerasw/essentials/MainActivity.kt @@ -10,6 +10,13 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -466,18 +473,36 @@ class MainActivity : FragmentActivity() { badges = mapOf(DIYTabs.APPS to viewModel.hasPendingUpdates.value) ) - when (tabs[currentPage]) { - DIYTabs.ESSENTIALS -> { - SetupFeatures( - viewModel = viewModel, - modifier = Modifier.padding(innerPadding), - searchRequested = searchRequested, - onSearchHandled = { searchRequested = false }, - onHelpClick = { showInstructionsSheet = true } + AnimatedContent( + targetState = currentPage, + transitionSpec = { + val animationSpec = tween(durationMillis = 400) + val slideOffset = 150 + + (fadeIn(animationSpec = animationSpec) + slideInVertically( + animationSpec = tween(durationMillis = 400), + initialOffsetY = { slideOffset } + )).togetherWith( + fadeOut(animationSpec = animationSpec) + slideOutVertically( + animationSpec = tween(durationMillis = 400), + targetOffsetY = { slideOffset } ) - } + ) + }, + label = "Tab Transition" + ) { targetPage -> + when (tabs[targetPage]) { + DIYTabs.ESSENTIALS -> { + SetupFeatures( + viewModel = viewModel, + modifier = Modifier.padding(innerPadding), + searchRequested = searchRequested, + onSearchHandled = { searchRequested = false }, + onHelpClick = { showInstructionsSheet = true } + ) + } - DIYTabs.FREEZE -> { + DIYTabs.FREEZE -> { FreezeGridUI( viewModel = viewModel, modifier = Modifier.padding(innerPadding), @@ -792,7 +817,8 @@ class MainActivity : FragmentActivity() { } } } - + } + override fun onResume() { super.onResume() viewModel.check(this) diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt index ff6eb58ae..aeb839818 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt @@ -1,6 +1,8 @@ package com.sameerasw.essentials.ui.components +import androidx.compose.animation.core.Spring import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -67,24 +69,33 @@ fun DIYFloatingToolbar( // Animate width for spacing val itemWidth by animateDpAsState( targetValue = if (expanded || isSelected) 48.dp else 0.dp, - animationSpec = tween(durationMillis = 300), + animationSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow + ), label = "item_width_$index" ) // Animate label width for active tab val labelWidth by animateDpAsState( targetValue = if (isSelected) 80.dp else 0.dp, - animationSpec = tween(durationMillis = 300), + animationSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow + ), label = "label_width_$index" ) // Animate spacer width val spacerWidth by animateDpAsState( targetValue = if (index < tabs.size - 1) 8.dp else 0.dp, - animationSpec = tween(durationMillis = 300), + animationSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow + ), label = "spacer_width_$index" ) - + // Always render the button, but animate its visibility if (itemWidth > 0.dp || isSelected) { IconButton( From 034a6cb73578def4c93ec5f94174cd1e32c23151 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 16:48:48 +0530 Subject: [PATCH 07/10] feat: re-enable bottom toolbar auto hiding --- .../sameerasw/essentials/ui/components/DIYFloatingToolbar.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt b/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt index aeb839818..419cc3f4a 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/components/DIYFloatingToolbar.kt @@ -56,7 +56,7 @@ fun DIYFloatingToolbar( androidx.compose.foundation.layout.WindowInsets.navigationBars ), expanded = expanded, -// scrollBehavior = scrollBehavior, + scrollBehavior = scrollBehavior, colors = FloatingToolbarDefaults.vibrantFloatingToolbarColors( toolbarContentColor = MaterialTheme.colorScheme.onSurface, toolbarContainerColor = MaterialTheme.colorScheme.primary, From d54f121a4befeb92ae3ed0e9cd110969b91447b4 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Wed, 25 Feb 2026 18:12:53 +0530 Subject: [PATCH 08/10] feat: Predictive back to main tab --- app/src/main/AndroidManifest.xml | 1 + .../com/sameerasw/essentials/MainActivity.kt | 37 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 01d89927b..12fd6ab93 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -50,6 +50,7 @@ android:localeConfig="@xml/locales_config" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" + android:enableOnBackInvokedCallback="true" android:theme="@style/Theme.Essentials"> 0) { progress -> + try { + progress.collect { backEvent -> + backProgress.snapTo(backEvent.progress) + } + currentPage = 0 + scope.launch { + backProgress.animateTo( + targetValue = 0f, + animationSpec = tween(durationMillis = 400) + ) + } + } catch (e: java.util.concurrent.CancellationException) { + scope.launch { + backProgress.animateTo( + targetValue = 0f, + animationSpec = tween(durationMillis = 300) + ) + } + } + } // Gracefully handle tab removal (e.g. disabling Developer Mode) LaunchedEffect(tabs) { @@ -489,6 +519,9 @@ class MainActivity : FragmentActivity() { ) ) }, + modifier = Modifier + .scale(1f - (backProgress.value * 0.05f)) + .alpha(1f - (backProgress.value * 0.3f)), label = "Tab Transition" ) { targetPage -> when (tabs[targetPage]) { From 1b833b13a7dd0094a2f0883a0e818669833523fc Mon Sep 17 00:00:00 2001 From: sameerasw Date: Fri, 27 Feb 2026 13:15:41 +0530 Subject: [PATCH 09/10] feat: Eye dropper QS tile --- app/src/main/AndroidManifest.xml | 10 ++++ .../services/tiles/ColorPickerTileService.kt | 60 +++++++++++++++++++ .../configs/QuickSettingsTilesSettingsUI.kt | 7 +++ .../main/res/drawable/rounded_colorize_24.xml | 5 ++ app/src/main/res/values/strings.xml | 4 ++ 5 files changed, 86 insertions(+) create mode 100644 app/src/main/java/com/sameerasw/essentials/services/tiles/ColorPickerTileService.kt create mode 100644 app/src/main/res/drawable/rounded_colorize_24.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 12fd6ab93..fff3f3096 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -581,6 +581,16 @@ + + + + + = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + val pendingIntent = PendingIntent.getActivity( + this, + 0, + intent, + PendingIntent.FLAG_IMMUTABLE + ) + startActivityAndCollapse(pendingIntent) + } else { + @Suppress("DEPRECATION") + startActivityAndCollapse(intent) + } + } catch (e: Exception) { + Handler(Looper.getMainLooper()).post { + Toast.makeText( + applicationContext, + getString(R.string.toast_eyedropper_failed), + Toast.LENGTH_SHORT + ).show() + } + } + } +} diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/QuickSettingsTilesSettingsUI.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/QuickSettingsTilesSettingsUI.kt index 142d599db..1857e14a5 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/QuickSettingsTilesSettingsUI.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/QuickSettingsTilesSettingsUI.kt @@ -249,6 +249,13 @@ fun QuickSettingsTilesSettingsUI( listOf("WRITE_SECURE_SETTINGS"), R.string.about_desc_usb_debugging ), + QSTileInfo( + R.string.tile_color_picker, + R.drawable.rounded_colorize_24, + com.sameerasw.essentials.services.tiles.ColorPickerTileService::class.java, + emptyList(), + R.string.about_desc_color_picker + ), QSTileInfo( R.string.tile_developer_options, R.drawable.rounded_mobile_code_24, diff --git a/app/src/main/res/drawable/rounded_colorize_24.xml b/app/src/main/res/drawable/rounded_colorize_24.xml new file mode 100644 index 000000000..1a75f5a03 --- /dev/null +++ b/app/src/main/res/drawable/rounded_colorize_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 97b6fe024..94708047e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -198,6 +198,9 @@ Auto Off USB Debugging + Color Picker + Are you sure you\'re on Androdi 17? (╯°_°)╯ + Eye Dropper On Off Custom Private DNS @@ -622,6 +625,7 @@ Toggle adaptive brightness.\n\nEnable or disable automatic screen brightness adjustment based on ambient light. Toggle Private DNS.\n\nCycle through Off, Automatic, and Private DNS provider modes. Toggle USB Debugging.\n\nEnable or disable ADB debugging access directly from the quick settings. + Launch the eye dropper tool to pick colors introduced in Android 17 BETA 2 Download From fcfc353af0e31ecc967e9f4d51fd55fa153fcd03 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Fri, 27 Feb 2026 13:19:49 +0530 Subject: [PATCH 10/10] fix: Battery notification QS tile invalid permissions --- .../domain/registry/PermissionRegistry.kt | 3 +++ .../essentials/utils/PermissionUIHelper.kt | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/app/src/main/java/com/sameerasw/essentials/domain/registry/PermissionRegistry.kt b/app/src/main/java/com/sameerasw/essentials/domain/registry/PermissionRegistry.kt index 5f5a98f32..f687dacba 100644 --- a/app/src/main/java/com/sameerasw/essentials/domain/registry/PermissionRegistry.kt +++ b/app/src/main/java/com/sameerasw/essentials/domain/registry/PermissionRegistry.kt @@ -52,12 +52,15 @@ fun initPermissionRegistry() { // Bluetooth permissions PermissionRegistry.register("BLUETOOTH_CONNECT", R.string.feat_batteries_title) PermissionRegistry.register("BLUETOOTH_SCAN", R.string.feat_batteries_title) + PermissionRegistry.register("BLUETOOTH_CONNECT", R.string.feat_battery_notification_title) + PermissionRegistry.register("BLUETOOTH_SCAN", R.string.feat_battery_notification_title) // Draw over other apps permission PermissionRegistry.register("DRAW_OVER_OTHER_APPS", R.string.feat_notification_lighting_title) // Post notifications permission PermissionRegistry.register("POST_NOTIFICATIONS", R.string.feat_caffeinate_title) + PermissionRegistry.register("POST_NOTIFICATIONS", R.string.feat_battery_notification_title) // Read phone state permission PermissionRegistry.register("READ_PHONE_STATE", R.string.search_smart_data_title) diff --git a/app/src/main/java/com/sameerasw/essentials/utils/PermissionUIHelper.kt b/app/src/main/java/com/sameerasw/essentials/utils/PermissionUIHelper.kt index 4ad711e15..4a42e5c94 100644 --- a/app/src/main/java/com/sameerasw/essentials/utils/PermissionUIHelper.kt +++ b/app/src/main/java/com/sameerasw/essentials/utils/PermissionUIHelper.kt @@ -252,6 +252,31 @@ object PermissionUIHelper { isGranted = viewModel.isDefaultBrowserSet.value ) + "BLUETOOTH_CONNECT", "BLUETOOTH_SCAN" -> PermissionItem( + iconRes = R.drawable.rounded_bluetooth_24, + title = R.string.perm_nearby_devices_title, + description = R.string.perm_nearby_devices_desc, + dependentFeatures = PermissionRegistry.getFeatures(key), + actionLabel = R.string.perm_action_grant, + action = { + if (activity != null) { + val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + arrayOf( + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_SCAN + ) + } else { + arrayOf( + android.Manifest.permission.BLUETOOTH, + android.Manifest.permission.BLUETOOTH_ADMIN + ) + } + ActivityCompat.requestPermissions(activity, permissions, 105) + } + }, + isGranted = viewModel.isBluetoothPermissionGranted.value + ) + else -> null } }