Skip to content

Commit c40b1ec

Browse files
committed
refactor pre-processor
1 parent f9bf22f commit c40b1ec

9 files changed

Lines changed: 68 additions & 104 deletions

File tree

app/src/androidTest/java/spam/blocker/service/RuleTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ class RuleTest {
300300
fun recent_app() {
301301
val spf = spf.RecentApps(ctx)
302302
val pkgs = listOf("my.pkg")
303-
spf.setDefaultMin(5)
303+
spf.setInXMin(5)
304304
spf.setList(pkgs.map { RecentAppInfo(it) })
305305

306306
// block all number

app/src/main/java/spam/blocker/config/Config.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,13 @@ class RecentApps : IConfig {
480480
val spf = spf.RecentApps(ctx)
481481
list.clear()
482482
list.addAll(spf.getList())
483-
inXMin = spf.getDefaultMin()
483+
inXMin = spf.getInXMin()
484484
}
485485

486486
override fun apply(ctx: Context) {
487487
val spf = spf.RecentApps(ctx)
488488
spf.setList(list)
489-
spf.setDefaultMin(inXMin)
489+
spf.setInXMin(inXMin)
490490
}
491491
}
492492

app/src/main/java/spam/blocker/db/BotTable.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ data class Bot(
3838
val lastLogTime: Long = 0,
3939
) {
4040

41-
// TODO: refactor this ..
41+
// TODO: refactor this .. later
4242

43-
// This is shown as the Bot summary on main UI
44-
// 3 types: Scheduled / Manual / CalendarEvent / SmsEvent / Call_or_SMS
43+
// This is displayed as the summary(the second row) in a bot card.
44+
// types: Scheduled / Manual / CalendarEvent / SmsEvent / CallEvent
4545
@Composable
4646
fun TriggerType(modifier: Modifier) {
4747
val ctx = LocalContext.current

app/src/main/java/spam/blocker/service/bot/Actions.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2370,6 +2370,9 @@ class CalendarEvent(
23702370
)
23712371
)
23722372
}
2373+
// Calendar Events modifies rules temporarily.
2374+
aCtx.isInMemory = true
2375+
23732376
return triggered
23742377
}
23752378

@@ -2581,11 +2584,20 @@ class CallEvent(
25812584
var enabled : Boolean = true,
25822585
var number: String = ".*",
25832586
var numberFlags: Int = Def.DefaultRegexFlags,
2584-
) : IPermissiveAction {
2587+
) : IAction {
2588+
override fun requiredPermissions(ctx: Context): List<PermissionWrapper> {
2589+
return listOf(
2590+
PermissionWrapper(Permission.callScreening),
2591+
)
2592+
}
25852593
@Composable
25862594
fun TriggerType(modifier: Modifier) {
25872595
RowVCenterSpaced(2, modifier = modifier) {
25882596
GreyIcon18(R.drawable.ic_incoming)
2597+
GreyLabel(
2598+
text = number,
2599+
modifier = M.padding(start = 4.dp)
2600+
)
25892601
}
25902602
}
25912603
fun isActivated(): Boolean {

app/src/main/java/spam/blocker/service/checker/Checker.kt

Lines changed: 42 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ import spam.blocker.service.bot.InterceptCall
3131
import spam.blocker.service.bot.InterceptSms
3232
import spam.blocker.service.bot.SmsEvent
3333
import spam.blocker.service.bot.executeAll
34-
import spam.blocker.service.checker.Checker.CalendarEventPreprocessor
35-
import spam.blocker.service.checker.Checker.CallPreprocessor
36-
import spam.blocker.service.checker.Checker.SmsPreprocessor
3734
import spam.blocker.ui.theme.Emerald
3835
import spam.blocker.ui.theme.LightMagenta
3936
import spam.blocker.ui.theme.Salmon
@@ -87,34 +84,58 @@ fun RegexRule.toNumberChecker(
8784
Checker.Number(ctx, this)
8885
}
8986

90-
// These classes are also `IChecker`, will be added to the checkers list. But they have
91-
// higher priorities and will get executed before other checkers. In this way, they can
92-
// temporary modify other checkers, e.g.: disable a regex rule on the fly.
87+
// A pre-processor is simply a WorkflowRunner, it's also an `IChecker` and will be added to the
88+
// checkers list. But they have higher priorities and will get executed before other checkers.
89+
// In this way, they can temporary modify other checkers, e.g.: disable a regex rule on the fly
90+
// without modifying the configuration.
9391
object Preprocessors {
94-
fun call(ctx: Context): List<CallPreprocessor> {
92+
93+
// Run a workflow.
94+
open class WorkflowRunner(
95+
val ctx: Context,
96+
val bot: Bot,
97+
) : IChecker {
98+
override fun priority(): Int {
99+
// To make sure it's executed before all other rules.
100+
return Int.MAX_VALUE - 1
101+
}
102+
override fun check(cCtx: CheckContext): ICheckResult? {
103+
val aCtx = ActionContext(
104+
logger = cCtx.logger,
105+
rawNumber = cCtx.rawNumber,
106+
smsContent = cCtx.smsContent,
107+
cCtx = cCtx,
108+
)
109+
bot.actions.executeAll(ctx, aCtx)
110+
111+
return null
112+
}
113+
}
114+
// Collect all `Call Event` that defined in Workflow section.
115+
fun call(ctx: Context): List<WorkflowRunner> {
95116
return BotTable.listAll(ctx)
96117
.filter {
97118
val firstAction = it.actions.firstOrNull()
98119
firstAction is CallEvent && firstAction.isActivated()
99120
}
100121
.map {
101-
CallPreprocessor(ctx, it)
122+
WorkflowRunner(ctx, it)
102123
}
103124
}
104-
105-
fun sms(ctx: Context): List<SmsPreprocessor> {
125+
// Collect all `SMS Event` that defined in Workflow section.
126+
fun sms(ctx: Context): List<WorkflowRunner> {
106127
return BotTable.listAll(ctx)
107128
.filter {
108129
val firstAction = it.actions.firstOrNull()
109130
firstAction is SmsEvent && firstAction.isActivated()
110131
}
111132
.map {
112-
SmsPreprocessor(ctx, it)
133+
WorkflowRunner(ctx, it)
113134
}
114135
}
115136

116-
// Return a list of workflows that match currently ongoing calendar events.
117-
fun calendarEvent(ctx: Context): List<CalendarEventPreprocessor> {
137+
// Collect all `Calendar Event` that defined in Workflow section.
138+
fun calendarEvent(ctx: Context): List<WorkflowRunner> {
118139
val bots = BotTable.listAll(ctx).filter {
119140
val firstAction = it.actions.firstOrNull()
120141
firstAction is CalendarEvent && firstAction.isActivated()
@@ -126,7 +147,7 @@ object Preprocessors {
126147
if (ongoingEvents.isEmpty()) // No calendar event currently occurring
127148
return listOf()
128149

129-
var ret = mutableListOf<CalendarEventPreprocessor>()
150+
var ret = mutableListOf<WorkflowRunner>()
130151

131152
ongoingEvents.forEach { eventTitle ->
132153
ret += bots
@@ -136,7 +157,7 @@ object Preprocessors {
136157
ce.eventTitle.regexMatches(eventTitle, ce.eventTitleFlags)
137158
}
138159
.map {
139-
CalendarEventPreprocessor(ctx, it, eventTitle)
160+
WorkflowRunner(ctx, it)
140161
}
141162
}
142163
return ret
@@ -662,7 +683,7 @@ class Checker { // for namespace only
662683

663684
val spf = spf.RecentApps(ctx)
664685

665-
val defaultDuration = spf.getDefaultMin() // in minutes
686+
val duration = spf.getInXMin() // in minutes
666687

667688
// To avoid querying db for each app, aggregate them by duration, like:
668689
// pkg.a,pkg.b@20,pkg.c
@@ -673,7 +694,7 @@ class Checker { // for namespace only
673694
// }
674695
// So it only queries db twice: for 5 min and 20 min.
675696
val aggregation = spf.getList().groupBy {
676-
it.duration ?: defaultDuration
697+
it.duration ?: duration
677698
}.mapValues { (_, values) ->
678699
values.map { it.pkgName }
679700
}
@@ -798,7 +819,7 @@ class Checker { // for namespace only
798819
var (winnerApi, result) = race(
799820
competitors = apis,
800821
timeoutMillis = timeLeft,
801-
runner = {
822+
runner = { api ->
802823
{ scope ->
803824
try {
804825
val aCtx = ActionContext(
@@ -807,7 +828,7 @@ class Checker { // for namespace only
807828
rawNumber = rawNumber,
808829
smsContent = cCtx.smsContent,
809830
)
810-
val success = it.actions.executeAll(ctx, aCtx)
831+
val success = api.actions.executeAll(ctx, aCtx)
811832

812833
if (!success) {
813834
null
@@ -1272,77 +1293,6 @@ class Checker { // for namespace only
12721293
}
12731294
}
12741295

1275-
// This will be executed before other checkers, it modifies other rules before they are executed.
1276-
// For example, if there's a calendar event "work"(7am-7pm) and currently it's 8am, the event is
1277-
// ongoing, so it will run actions like `Modify Rules`.
1278-
open class Preprocessor : IChecker {
1279-
override fun priority(): Int {
1280-
return Int.MAX_VALUE - 1
1281-
}
1282-
1283-
override fun check(cCtx: CheckContext): ICheckResult? {
1284-
return null
1285-
}
1286-
}
1287-
class CalendarEventPreprocessor(
1288-
private val ctx: Context,
1289-
private val bot: Bot,
1290-
private val eventTitle: String,
1291-
) : Preprocessor() {
1292-
1293-
override fun check(cCtx: CheckContext): ICheckResult? {
1294-
val aCtx = ActionContext(
1295-
logger = cCtx.logger,
1296-
rawNumber = cCtx.rawNumber,
1297-
smsContent = cCtx.smsContent,
1298-
cCtx = cCtx,
1299-
isInMemory = true,
1300-
)
1301-
bot.actions.executeAll(ctx, aCtx)
1302-
1303-
// this is not a checker, it's just a pre-processor, always return null
1304-
return null
1305-
}
1306-
}
1307-
1308-
// This will be executed before other checkers, it modifies the incoming number before it's checked.
1309-
class CallPreprocessor(
1310-
private val ctx: Context,
1311-
private val bot: Bot,
1312-
) : Preprocessor() {
1313-
override fun check(cCtx: CheckContext): ICheckResult? {
1314-
val aCtx = ActionContext(
1315-
logger = cCtx.logger,
1316-
rawNumber = cCtx.rawNumber,
1317-
smsContent = cCtx.smsContent,
1318-
cCtx = cCtx,
1319-
)
1320-
bot.actions.executeAll(ctx, aCtx)
1321-
1322-
// this is not a checker, it's just a pre-processor, always return null
1323-
return null
1324-
}
1325-
}
1326-
1327-
// This will be executed before other checkers, it modifies the incoming number before it's checked.
1328-
class SmsPreprocessor(
1329-
private val ctx: Context,
1330-
private val bot: Bot,
1331-
) : Preprocessor() {
1332-
override fun check(cCtx: CheckContext): ICheckResult? {
1333-
val aCtx = ActionContext(
1334-
logger = cCtx.logger,
1335-
rawNumber = cCtx.rawNumber,
1336-
smsContent = cCtx.smsContent,
1337-
cCtx = cCtx,
1338-
)
1339-
bot.actions.executeAll(ctx, aCtx)
1340-
1341-
// this is not a checker, it's just a pre-processor, always return null
1342-
return null
1343-
}
1344-
}
1345-
13461296

13471297
companion object {
13481298

@@ -1375,6 +1325,7 @@ class Checker { // for namespace only
13751325
return result
13761326
}
13771327

1328+
// The call passed all rules.
13781329
logger?.success(ctx.getString(R.string.passed_by_default))
13791330
// pass by default
13801331
return ByDefault()
@@ -1448,6 +1399,7 @@ class Checker { // for namespace only
14481399
return result
14491400
}
14501401

1402+
// The SMS message passed all rules.
14511403
logger?.success(ctx.getString(R.string.passed_by_default))
14521404

14531405
// pass by default

app/src/main/java/spam/blocker/ui/setting/quick/RecentApps.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ private fun PopupConfig(
207207
onValueChange = { newValue, hasError ->
208208
if (!hasError) {
209209
inXMin.value = newValue
210-
spf.RecentApps(ctx).setDefaultMin(newValue!!)
210+
spf.RecentApps(ctx).setInXMin(newValue!!)
211211
}
212212
},
213213
labelId = R.string.within_minutes,
@@ -221,7 +221,7 @@ fun RecentApps() {
221221
val ctx = LocalContext.current
222222
val spf = spf.RecentApps(ctx)
223223

224-
val defaultInXMin = remember { mutableStateOf<Int?>(spf.getDefaultMin()) }
224+
val defaultInXMin = remember { mutableStateOf<Int?>(spf.getInXMin()) }
225225

226226
val buttonPopupTrigger = rememberSaveable { mutableStateOf(false) }
227227
val appsPopupTrigger = rememberSaveable { mutableStateOf(false) }

app/src/main/java/spam/blocker/util/PermissionChain.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ class PermissionChain() {
9191
contract = ActivityResultContracts.StartActivityForResult()
9292
) { _ ->
9393
// The app process will be killed when the "all file access" is granted and then revoked
94-
// (by turning on the permission switch in system settings and then immediately turn it off).
94+
// (by turning on the permission switch in system settings and then immediately turned off).
9595
// After returning back to this app, android will launch a new process, but these
96-
// lateinit variables haven't been initialized in the new process, which leads to a crash.
96+
// `lateinit` variables haven't been initialized in the new process, which leads to a crash.
9797
// So check it first, if it's uninitialized, ignore and return.
9898
if (!::curr.isInitialized) {
9999
return@rememberLauncherForActivityResult

app/src/main/java/spam/blocker/util/SharedPref.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,10 @@ class spf { // for namespace only
314314
}
315315
setList(l)
316316
}
317-
fun getDefaultMin() : Int {
317+
fun getInXMin() : Int {
318318
return readInt(Def.SETTING_RECENT_APP_IN_X_MIN, 5)
319319
}
320-
fun setDefaultMin(inXMin : Int) {
320+
fun setInXMin(inXMin : Int) {
321321
writeInt(Def.SETTING_RECENT_APP_IN_X_MIN, inXMin)
322322
}
323323
}

app/src/main/java/spam/blocker/util/race.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import java.util.concurrent.atomic.AtomicInteger
1818
// return:
1919
// Pair(
2020
// the winner, one of the competitors
21-
// the first non-null value
21+
// the first non-null value as the result
2222
// )
2323
@Suppress("UNCHECKED_CAST")
2424
private suspend fun <C, R> racing(

0 commit comments

Comments
 (0)