Skip to content

Commit 5b11a79

Browse files
committed
feat(blocklist): frame rule workspaces in dark cards
1 parent c6927cb commit 5b11a79

4 files changed

Lines changed: 74 additions & 58 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ All notable changes to CallShield will be documented in this file.
44

55
## Unreleased
66

7+
- Blocklist now has a clearer rules heading, an outlined count card, pill tabs
8+
for each rule type, and a framed empty state.
79
- Recent calls now uses compact, neutral history cards and shows a Retry card
810
when Android cannot load the call log. Calls already loaded stay visible.
911
- Blocked activity now has a clear heading, a framed empty state and compact

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ language in [issue #7](https://github.com/SysAdminDoc/CallShield/issues/7).
542542
| URL Safety | Local spam-domain data; optional PhishTank and OpenPhish |
543543
| Verification | Local Gradle, lint, and release-artifact checks |
544544
| Tests | 1559 JVM unit tests (JUnit) |
545-
| Strings | 1629 string resources and 38 plural groups (translation-ready) |
545+
| Strings | 1631 string resources and 38 plural groups (translation-ready) |
546546
| Accessibility | 100+ content descriptions, 48dp touch targets |
547547
| Min SDK | 29 (Android 10) |
548548
| Target SDK | 36 |

‎app/src/main/java/com/sysadmindoc/callshield/ui/screens/main/BlocklistScreen.kt‎

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package com.sysadmindoc.callshield.ui.screens.main
22

33
import androidx.activity.compose.rememberLauncherForActivityResult
44
import androidx.activity.result.contract.ActivityResultContracts
5+
import androidx.compose.foundation.BorderStroke
56
import androidx.compose.foundation.background
7+
import androidx.compose.foundation.border
68
import androidx.compose.foundation.clickable
79
import androidx.compose.foundation.horizontalScroll
810
import androidx.compose.foundation.layout.Arrangement
@@ -340,6 +342,22 @@ fun BlocklistScreen(viewModel: MainViewModel) {
340342

341343
Box(modifier = Modifier.fillMaxSize()) {
342344
Column(modifier = Modifier.fillMaxSize()) {
345+
Column(
346+
modifier = Modifier.fillMaxWidth().padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 8.dp),
347+
verticalArrangement = Arrangement.spacedBy(4.dp),
348+
) {
349+
Text(
350+
stringResource(R.string.blocklist_heading),
351+
style = MaterialTheme.typography.headlineSmall,
352+
fontWeight = FontWeight.Bold,
353+
color = CatText,
354+
)
355+
Text(
356+
stringResource(R.string.blocklist_intro),
357+
style = MaterialTheme.typography.bodySmall,
358+
color = CatSubtext,
359+
)
360+
}
343361
BlocklistOverviewCard(
344362
modifier =
345363
Modifier
@@ -725,55 +743,45 @@ private fun BlocklistOverviewCard(
725743
workspace: BlocklistWorkspaceModel,
726744
modifier: Modifier = Modifier,
727745
) {
728-
Column(
729-
modifier = modifier,
730-
verticalArrangement = Arrangement.spacedBy(8.dp),
731-
) {
732-
SectionHeader(workspace.title, CatGreen)
733-
Text(
734-
text =
735-
if (workspace.addActionLabel == null) {
736-
pluralStringResource(
737-
R.plurals.blocklist_count_saved,
738-
workspace.count,
739-
workspace.count,
746+
PremiumCard(modifier = modifier) {
747+
Column(
748+
modifier = Modifier.fillMaxWidth().padding(16.dp),
749+
verticalArrangement = Arrangement.spacedBy(8.dp),
750+
) {
751+
SectionHeader(workspace.title, CatGreen)
752+
Text(
753+
text =
754+
if (workspace.addActionLabel == null) {
755+
pluralStringResource(R.plurals.blocklist_count_saved, workspace.count, workspace.count)
756+
} else {
757+
pluralStringResource(R.plurals.blocklist_count_active_rules, workspace.count, workspace.count)
758+
},
759+
style = MaterialTheme.typography.titleLarge,
760+
fontWeight = FontWeight.SemiBold,
761+
color = CatText,
762+
)
763+
Text(workspace.subtitle, style = MaterialTheme.typography.bodySmall, color = CatSubtext)
764+
Row(
765+
modifier = Modifier.fillMaxWidth(),
766+
horizontalArrangement = Arrangement.spacedBy(6.dp),
767+
verticalAlignment = Alignment.CenterVertically,
768+
) {
769+
workspace.primaryUtilityLabel?.let { label ->
770+
PremiumCompactButton(
771+
label = label,
772+
icon = Icons.Default.FileOpen,
773+
color = CatGreen,
774+
onClick = { workspace.onPrimaryUtility?.invoke() },
740775
)
741-
} else {
742-
pluralStringResource(
743-
R.plurals.blocklist_count_active_rules,
744-
workspace.count,
745-
workspace.count,
776+
}
777+
workspace.secondaryUtilityLabel?.let { label ->
778+
PremiumCompactButton(
779+
label = label,
780+
icon = Icons.Default.Share,
781+
color = CatGreen,
782+
onClick = { workspace.onSecondaryUtility?.invoke() },
746783
)
747-
},
748-
style = MaterialTheme.typography.headlineMedium,
749-
fontWeight = FontWeight.SemiBold,
750-
color = CatText,
751-
)
752-
Text(
753-
text = workspace.subtitle,
754-
style = MaterialTheme.typography.bodyMedium,
755-
color = CatSubtext,
756-
)
757-
Row(
758-
modifier = Modifier.fillMaxWidth(),
759-
horizontalArrangement = Arrangement.spacedBy(6.dp),
760-
verticalAlignment = Alignment.CenterVertically,
761-
) {
762-
workspace.primaryUtilityLabel?.let { label ->
763-
PremiumCompactButton(
764-
label = label,
765-
icon = Icons.Default.FileOpen,
766-
color = CatGreen,
767-
onClick = { workspace.onPrimaryUtility?.invoke() },
768-
)
769-
}
770-
workspace.secondaryUtilityLabel?.let { label ->
771-
PremiumCompactButton(
772-
label = label,
773-
icon = Icons.Default.Share,
774-
color = CatGreen,
775-
onClick = { workspace.onSecondaryUtility?.invoke() },
776-
)
784+
}
777785
}
778786
}
779787
}
@@ -873,19 +881,17 @@ private fun RuleTabLabel(
873881
label: String,
874882
selected: Boolean,
875883
) {
876-
Column(horizontalAlignment = Alignment.CenterHorizontally) {
884+
Surface(
885+
color = if (selected) CatGreen.copy(alpha = 0.12f) else SurfaceBright,
886+
shape = RoundedCornerShape(24.dp),
887+
border = BorderStroke(1.dp, if (selected) CatGreen else CatOverlay.copy(alpha = 0.3f)),
888+
) {
877889
Text(
878890
text = label,
891+
modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp),
879892
style = MaterialTheme.typography.labelLarge,
880893
fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Medium,
881-
)
882-
Spacer(Modifier.height(7.dp))
883-
Box(
884-
modifier =
885-
Modifier
886-
.width(36.dp)
887-
.height(2.dp)
888-
.background(if (selected) CatGreen else Color.Transparent),
894+
color = if (selected) CatText else CatSubtext,
889895
)
890896
}
891897
}
@@ -906,7 +912,13 @@ private fun EmptyStateCard(
906912
contentAlignment = Alignment.Center,
907913
) {
908914
Column(
909-
modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 28.dp),
915+
modifier =
916+
Modifier
917+
.fillMaxWidth()
918+
.clip(RoundedCornerShape(20.dp))
919+
.background(SurfaceBright)
920+
.border(1.dp, CatOverlay.copy(alpha = 0.35f), RoundedCornerShape(20.dp))
921+
.padding(horizontal = 20.dp, vertical = 28.dp),
910922
horizontalAlignment = Alignment.CenterHorizontally,
911923
verticalArrangement = Arrangement.spacedBy(10.dp),
912924
) {

‎app/src/main/res/values/strings.xml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@
216216
<string name="blocked_log_sms">SMS</string>
217217

218218
<!-- Blocklist Screen -->
219+
<string name="blocklist_heading">Blocklist &amp; rules</string>
220+
<string name="blocklist_intro">Control who can reach you and how CallShield handles risky calls and texts.</string>
219221
<string name="blocklist_tab_blocked_short">Blocked</string>
220222
<string name="blocklist_tab_wildcards_short">Wildcards</string>
221223
<string name="blocklist_tab_keywords_short">Keywords</string>

0 commit comments

Comments
 (0)