├── app
├── .gitignore
├── src
│ └── main
│ │ ├── ic_launcher-playstore.png
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ ├── drawable
│ │ │ ├── ic_history_indicator_1.png
│ │ │ ├── ic_history_indicator_2.png
│ │ │ ├── ic_history_indicator_3.png
│ │ │ ├── ic_dropdown_footer.xml
│ │ │ ├── ic_exit.xml
│ │ │ ├── ic_right_arrow.xml
│ │ │ ├── ic_dropdown_arrow.xml
│ │ │ ├── ic_time_slot.xml
│ │ │ ├── ic_sms.xml
│ │ │ ├── ic_sms_pass.xml
│ │ │ ├── ic_sim_card.xml
│ │ │ ├── ic_http_header.xml
│ │ │ ├── ic_toggle.xml
│ │ │ ├── ic_sms_blocked.xml
│ │ │ ├── ic_contact_circle.xml
│ │ │ ├── ic_question.xml
│ │ │ ├── ic_reorder.xml
│ │ │ ├── ic_priority.xml
│ │ │ ├── ic_duration.xml
│ │ │ ├── ic_call.xml
│ │ │ ├── ic_fail_red.xml
│ │ │ ├── ic_flags.xml
│ │ │ ├── ic_repeat.xml
│ │ │ ├── ic_copy.xml
│ │ │ ├── ic_http.xml
│ │ │ ├── ic_number_sign.xml
│ │ │ ├── ic_bell_mute.xml
│ │ │ ├── ic_clear.xml
│ │ │ ├── ic_warning.xml
│ │ │ ├── ic_note.xml
│ │ │ ├── ic_filter.xml
│ │ │ ├── ic_flag_catalan.xml
│ │ │ ├── ic_unknown_app_icon.xml
│ │ │ ├── ic_weekly.xml
│ │ │ ├── ic_find.xml
│ │ │ ├── ic_regex.xml
│ │ │ ├── ic_heads_up.xml
│ │ │ ├── ic_workflow.xml
│ │ │ ├── ic_no.xml
│ │ │ ├── ic_statusbar_shade.xml
│ │ │ ├── ic_yes.xml
│ │ │ ├── ic_category.xml
│ │ │ ├── ic_file_read.xml
│ │ │ ├── ic_hourglass.xml
│ │ │ ├── ic_incoming.xml
│ │ │ ├── ic_contact_square.xml
│ │ │ ├── ic_contact_group.xml
│ │ │ ├── ic_history_cleanup.xml
│ │ │ ├── ic_delay.xml
│ │ │ ├── ic_calendar.xml
│ │ │ ├── ic_recycle_bin.xml
│ │ │ ├── ic_settings.xml
│ │ │ ├── ic_check_circle.xml
│ │ │ ├── ic_mms.xml
│ │ │ ├── ic_file_write.xml
│ │ │ ├── ic_check_green.xml
│ │ │ ├── ic_backup_import.xml
│ │ │ ├── ic_link.xml
│ │ │ ├── ic_call_miss.xml
│ │ │ ├── ic_music.xml
│ │ │ ├── ic_bell_ringing.xml
│ │ │ ├── ic_daily.xml
│ │ │ ├── ic_tag.xml
│ │ │ ├── ic_xml.xml
│ │ │ ├── ic_backup_export.xml
│ │ │ ├── ic_tile.xml
│ │ │ ├── ic_tube.xml
│ │ │ ├── ic_notification.xml
│ │ │ ├── ic_open_msg.xml
│ │ │ ├── ic_post.xml
│ │ │ ├── ic_replace.xml
│ │ │ ├── ic_tap.xml
│ │ │ ├── ic_call_blocked.xml
│ │ │ ├── ic_csv.xml
│ │ │ ├── ic_xpath.xml
│ │ │ ├── ic_multi_sms.xml
│ │ │ └── ic_tile_custom.xml
│ │ ├── values
│ │ │ ├── themes.xml
│ │ │ └── strings_24.xml
│ │ ├── xml
│ │ │ ├── keep_no_shrink.xml
│ │ │ ├── backup_rules.xml
│ │ │ └── data_extraction_rules.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── values-zh-rTW
│ │ │ ├── strings_24.xml
│ │ │ ├── strings_7.xml
│ │ │ ├── strings_4.xml
│ │ │ ├── strings_3.xml
│ │ │ └── strings_16.xml
│ │ ├── values-zh-rCN
│ │ │ ├── strings_24.xml
│ │ │ ├── strings_7.xml
│ │ │ ├── strings_4.xml
│ │ │ ├── strings_16.xml
│ │ │ └── strings_3.xml
│ │ ├── values-ja
│ │ │ ├── strings_24.xml
│ │ │ ├── strings_7.xml
│ │ │ └── strings_4.xml
│ │ ├── values-tr
│ │ │ └── strings_24.xml
│ │ ├── values-ar
│ │ │ └── strings_24.xml
│ │ ├── values-iw
│ │ │ └── strings_24.xml
│ │ ├── values-fa
│ │ │ └── strings_24.xml
│ │ ├── values-in
│ │ │ └── strings_24.xml
│ │ ├── values-it
│ │ │ └── strings_24.xml
│ │ ├── values-ru
│ │ │ └── strings_24.xml
│ │ ├── values-uk
│ │ │ └── strings_24.xml
│ │ ├── values-gal
│ │ │ └── strings_24.xml
│ │ ├── values-pt-rBR
│ │ │ └── strings_24.xml
│ │ ├── values-es
│ │ │ └── strings_24.xml
│ │ ├── values-ca
│ │ │ └── strings_24.xml
│ │ ├── values-de
│ │ │ └── strings_24.xml
│ │ └── values-fr
│ │ │ └── strings_24.xml
│ │ └── java
│ │ └── spam
│ │ └── blocker
│ │ ├── ui
│ │ ├── main
│ │ │ └── Debug.kt
│ │ ├── widgets
│ │ │ ├── Form.kt
│ │ │ ├── GreenDot.kt
│ │ │ ├── OutlinedCard.kt
│ │ │ ├── Animation.kt
│ │ │ ├── NonLazyGrid.kt
│ │ │ ├── SnackBar.kt
│ │ │ └── CheckBox.kt
│ │ ├── setting
│ │ │ ├── misc
│ │ │ │ ├── Logcat.kt
│ │ │ │ ├── Theme.kt
│ │ │ │ └── About.kt
│ │ │ ├── bot
│ │ │ │ ├── BotViewModel.kt
│ │ │ │ ├── EditActionDialog.kt
│ │ │ │ └── BotCard.kt
│ │ │ └── api
│ │ │ │ └── ApiViewModel.kt
│ │ ├── theme
│ │ │ ├── Type.kt
│ │ │ └── Color.kt
│ │ ├── history
│ │ │ ├── HistoryViewModel.kt
│ │ │ └── HistoryScreen.kt
│ │ └── NotificationTrampolineActivity.kt
│ │ ├── util
│ │ ├── Logcat.kt
│ │ ├── Clipboard.kt
│ │ ├── MockkWorkaround.kt
│ │ ├── Flag.kt
│ │ ├── pdu
│ │ │ ├── util
│ │ │ │ └── PduCacheEntry.java
│ │ │ ├── InvalidHeaderValueException.java
│ │ │ └── MmsException.java
│ │ ├── Xml.kt
│ │ ├── RingtoneUtil.kt
│ │ ├── Algorithm.kt
│ │ ├── AnnotatedFormatter.kt
│ │ └── AppInfo.kt
│ │ └── service
│ │ ├── Tile.kt
│ │ ├── CopyToClipboardReceiver.kt
│ │ └── CustomTile.kt
└── proguard-rules.pro
├── metadata
├── en-US
│ ├── changelogs
│ │ ├── 1.txt
│ │ ├── 11.txt
│ │ ├── 410.txt
│ │ ├── 12.txt
│ │ ├── 114.txt
│ │ ├── 406.txt
│ │ ├── 118.txt
│ │ ├── 18.txt
│ │ ├── 411.txt
│ │ ├── 113.txt
│ │ ├── 110.txt
│ │ ├── 409.txt
│ │ ├── 111.txt
│ │ ├── 402.txt
│ │ ├── 408.txt
│ │ ├── 302.txt
│ │ ├── 201.txt
│ │ ├── 418.txt
│ │ ├── 13.txt
│ │ ├── 403.txt
│ │ ├── 115.txt
│ │ ├── 301.txt
│ │ ├── 417.txt
│ │ ├── 407.txt
│ │ ├── 421.txt
│ │ ├── 17.txt
│ │ ├── 14.txt
│ │ ├── 119.txt
│ │ ├── 412.txt
│ │ ├── 112.txt
│ │ ├── 116.txt
│ │ ├── 117.txt
│ │ ├── 202.txt
│ │ ├── 16.txt
│ │ ├── 420.txt
│ │ ├── 401.txt
│ │ ├── 405.txt
│ │ ├── 19.txt
│ │ ├── 419.txt
│ │ ├── 500.txt
│ │ ├── 303.txt
│ │ ├── 120.txt
│ │ ├── 200.txt
│ │ ├── 416.txt
│ │ ├── 15.txt
│ │ ├── 305.txt
│ │ ├── 404.txt
│ │ ├── 415.txt
│ │ ├── 414.txt
│ │ ├── 304.txt
│ │ ├── 300.txt
│ │ ├── 413.txt
│ │ └── 400.txt
│ ├── title.txt
│ ├── short_description.txt
│ ├── images
│ │ ├── icon.png
│ │ └── phoneScreenshots
│ │ │ ├── 1.history.png
│ │ │ ├── 2.settings.png
│ │ │ └── 3.notification.png
│ └── full_description.txt
└── ru
│ ├── title.txt
│ ├── short_description.txt
│ └── full_description.txt
├── .github
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── 3.discussion.yml
│ ├── 2.feature_request.yml
│ ├── 4.share.yml
│ └── 1.bug_report.yml
├── workflows
│ ├── labeler.yml
│ └── share.yml
└── labeler.yml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── local.properties
├── settings.gradle.kts
├── LICENSE
├── gradle.properties
└── auto_translate
├── retry.go
└── go.mod
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/1.txt:
--------------------------------------------------------------------------------
1 | first release
--------------------------------------------------------------------------------
/metadata/en-US/title.txt:
--------------------------------------------------------------------------------
1 | SpamBlocker (Call & SMS)
--------------------------------------------------------------------------------
/metadata/ru/title.txt:
--------------------------------------------------------------------------------
1 | СпамБлокер (Звонки и SMS)
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/11.txt:
--------------------------------------------------------------------------------
1 | Adapt Android 10+
--------------------------------------------------------------------------------
/metadata/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Spam Call/SMS blocker
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/410.txt:
--------------------------------------------------------------------------------
1 | Language support:
2 | - Arab(ar)
3 |
--------------------------------------------------------------------------------
/metadata/ru/short_description.txt:
--------------------------------------------------------------------------------
1 | Блокировщик спама звонков и SMS
2 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/12.txt:
--------------------------------------------------------------------------------
1 | Add feature: SMS content filter for particular number
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/114.txt:
--------------------------------------------------------------------------------
1 | fix:
2 | - crash when priority is empty
3 | new:
4 | - language support: ua
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/406.txt:
--------------------------------------------------------------------------------
1 | Fix:
2 | - The unread count indicator on the bottom bar does not appear at startup
--------------------------------------------------------------------------------
/metadata/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/metadata/en-US/images/icon.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/118.txt:
--------------------------------------------------------------------------------
1 | New:
2 | regex flag "Raw Number" for not optimizing number
3 | Enhancement:
4 | import rules from .csv file
5 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/18.txt:
--------------------------------------------------------------------------------
1 | new:
2 | - support STIR attestation
3 | - always allow emergency call, with max priority
4 | - multi-language support
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_history_indicator_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/drawable/ic_history_indicator_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_history_indicator_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/drawable/ic_history_indicator_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_history_indicator_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/drawable/ic_history_indicator_3.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/1.history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/metadata/en-US/images/phoneScreenshots/1.history.png
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/2.settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/metadata/en-US/images/phoneScreenshots/2.settings.png
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/main/Debug.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.main
2 |
3 |
4 | import android.content.Context
5 |
6 | fun debug(ctx: Context) {
7 |
8 | }
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/411.txt:
--------------------------------------------------------------------------------
1 | Fix:
2 | - Unread badge UI broken with large number.
3 | - No SMS notification sound in lockscreen if the SMS app is in the foreground.
--------------------------------------------------------------------------------
/metadata/en-US/images/phoneScreenshots/3.notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/metadata/en-US/images/phoneScreenshots/3.notification.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aj3423/SpamBlocker/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/113.txt:
--------------------------------------------------------------------------------
1 | fix:
2 | - RepeatedCall/Dialed doesn't work with numbers that start with 0
3 |
4 | new:
5 | - language support: de, es
6 | - add "About" page
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle/
2 | .idea/
3 | .kotlin/
4 | *.db
5 | build/
6 | app/release/
7 | app/debug/
8 | auto_translate/go.sum
9 | local.properties
10 | auto_translate/.vscode/
11 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/110.txt:
--------------------------------------------------------------------------------
1 | new:
2 | - crash report
3 | fix:
4 | - crash with long rule list(1000+)
5 | - unread mark(the red dot) in the history log shows the opposite status
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/409.txt:
--------------------------------------------------------------------------------
1 | New
2 | - Emergency mode:
3 | Allow all calls for a period of time after dialing an emergency number.
4 |
5 | Language support:
6 | - Catalan(ca)
7 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/111.txt:
--------------------------------------------------------------------------------
1 | fix:
2 | - db crash when upgrading from old version
3 | - msg rule doesn't work for long message
4 | - answer & hang up not work on android 14
5 | - dont show block type icon for msg rule
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/402.txt:
--------------------------------------------------------------------------------
1 | Improvement
2 | - Answer+HangUp delay, use cases:
3 | - Call recording, set a 8-seconds delay and install a recording app.
4 | - Prevent calls from going to voicemail due to rapid disconnection.
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/408.txt:
--------------------------------------------------------------------------------
1 | Fix
2 | - Import csv to spam db doesn't work on Android 10
3 |
4 | Enhancement
5 | - Spam notifications are now grouped together
6 |
7 | Maintenance
8 | - Bump preset API Gemini to 2.0-flash
9 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/302.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Each release will also include an apk that doesn't require internet permission. (No android.permission.INTERNET in manifest xml)
3 |
4 | Fix: workflow not re-scheduled after Delete/Undelete
5 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/201.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Option to disable history logging, or auto expire
3 | - Rule schedule now supports two-day time spans, like 21:00-05:00
4 | - "Search Rule" context menu item
5 | - Language support: Galician (gal)
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/418.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Workflow
3 | - "Ringtone": Customize ringtone for regex rules
4 | - "Quick Tile": Toggle regex rules using a Quick Settings Tile
5 |
6 | Fixes:
7 | - Regex rules become case-sensitive after restored from backup.
8 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/13.txt:
--------------------------------------------------------------------------------
1 | - fix: long rule breaks UI
2 | - feature: filter for showing passed/blocked
3 | - feature: notification type per rule
4 | - RepeatedCall also checks for text
5 | - add option "x times in y mins" for RepeatedCall
6 | - add option "in x mins" for RecentApps
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/403.txt:
--------------------------------------------------------------------------------
1 | fix
2 | - Unable to add new SMS rule after upgrading to v4.2
3 |
4 | Improvement
5 | - New regex flag: "Omit Country Code", allowing matching international numbers like `+33111` or `+44111` with simpler regex `111.*` (instead of `(33|44)*111.*`)
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/3.discussion.yml:
--------------------------------------------------------------------------------
1 | name: Discussion
2 | description: Start a discussion
3 | labels: [discussion]
4 | body:
5 |
6 | - type: textarea
7 | id: detail
8 | attributes:
9 | label: Talk about anything
10 | validations:
11 | required: true
12 |
13 |
14 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/115.txt:
--------------------------------------------------------------------------------
1 | breaking:
2 | RecentApps now only works for apps that have INTERNET access(to get rid of QUERY_ALL_PACKAGES)
3 |
4 | improvement:
5 | no longer require permission QUERY_ALL_PACKAGES
6 | improve launch speed
7 | reduce apk size 13Mb -> 3Mb (using R8)
8 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/301.txt:
--------------------------------------------------------------------------------
1 | Enhancement:
2 | - Collapse/expand the regex list by clicking the list header.
3 |
4 | Fix:
5 | - Imported workflow not saved.
6 | - Scheduled task not run.
7 | - If you are upgrading from v3.0, please do a backup and restore, it will fix all the schedule issues.
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2.feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest a new feature
3 | labels: [new feature]
4 | body:
5 |
6 | - type: textarea
7 | id: feature-description
8 | attributes:
9 | label: The feature
10 | validations:
11 | required: true
12 |
13 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/417.txt:
--------------------------------------------------------------------------------
1 | Fixes:
2 | - Sql injection issue that caused by alpha numbers like `McDonald's`
3 | - Hang-up mode doesn't work with "private" numbers
4 | - Regression issue: DotMatchAll is removed but not enabled by default, causing regex to fail matching multiline SMS.
5 | - UI doesn't change after backup restore
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/407.txt:
--------------------------------------------------------------------------------
1 | New
2 | - Anti SMS bombing
3 | Prevent massive continuous OTP messages.
4 |
5 | Improvements
6 | - History and spam-database expiry
7 | Settings like <0 =0 >0 are changed to "no-log/never-expire/expiry-days"
8 | - workflow action ModifyRules now supports all rules.(for remote configuring for seniors)
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Apr 12 17:10:25 CST 2025
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
5 | networkTimeout=10000
6 | validateDistributionUrl=true
7 | zipStoreBase=GRADLE_USER_HOME
8 | zipStorePath=wrapper/dists
9 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/421.txt:
--------------------------------------------------------------------------------
1 | Breaking change:
2 | - Workflow triggers refactored
3 | Current settings will be upgraded automatically. Old backups are now incompatible(just workflow part).
4 | Re-backup if necessary, ignore if you don't use workflow.
5 |
6 | Fix:
7 | - Workflow "Ringtone" doesn't work when "Vibrate First Then Ring" is enabled.
8 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/17.txt:
--------------------------------------------------------------------------------
1 | new:
2 | support quick settings tile
3 | fix:
4 | contact number with local area code doesn't match
5 | crash if RecentApp is uninstalled
6 | change:
7 | show sms content instead of block reason in notification
8 | recentapp icon now scrollable
9 | READ_SMS is now optional for RepeatedCall/Dialed
10 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file must *NOT* be checked into Version Control Systems,
2 | # as it contains information specific to your local configuration.
3 | #
4 | # Location of the SDK. This is only used by Gradle.
5 | # For customization when using a Version Control System, please read the
6 | # header note.
7 | #Fri Aug 23 16:54:05 CST 2024
8 | sdk.dir=/root/Android/Sdk
9 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | - feature: testing rules
2 | - feature: filter for showing passed/blocked
3 | - feature: notify type per rule
4 | - fix: contact with country code not match
5 | - add option "x times in y mins" for RepeatedCall
6 | - add option "in x mins" for RecentApps
7 | - improved notification, UI, tooltip
8 | - no longer require permission READ_CALL_LOG
--------------------------------------------------------------------------------
/app/src/main/res/xml/keep_no_shrink.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/metadata/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | It blocks unwanted calls & SMS messages without replacing your default call/SMS app.
2 |
3 | Filters:
4 |
5 | 1. Regex rule for number & SMS content.
6 | 2. Contact
7 | 3. STIR attestation
8 | 4. Repeated call
9 | 5. Dialed number
10 | 6. Recently used apps
11 | 7. Time schedule
12 |
13 | Details: https://github.com/aj3423/SpamBlocker
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/Logcat.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.util
2 |
3 | import android.util.Log
4 |
5 | const val TAG = "SpamBlocker"
6 |
7 | fun logd(str: String) {
8 | Log.d(TAG, str)
9 | }
10 | fun logi(str: String) {
11 | Log.i(TAG, str)
12 | }
13 | fun logw(str: String) {
14 | Log.w(TAG, str)
15 | }
16 | fun loge(str: String) {
17 | Log.e(TAG, str)
18 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dropdown_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/119.txt:
--------------------------------------------------------------------------------
1 | improvement:
2 | - add context menu for history record
3 | - Add to new rule
4 | - Copy number
5 | - language
6 | - add "follow system"(by default)
7 | - add icons
8 | - show double-sms warning when notification is enabled for the default sms app
9 | fix:
10 | - low probability crash: "Exception: unable to find fragment constructor"
11 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/412.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Push Alert
3 | Allow calls after receiving push notifications from other apps. Use case:
4 | - A notification like: "Your order has been taken by driver ..."
5 | The driver may then call you to confirm details.
6 |
7 | Fix:
8 | - Crash when testing with invalid regex
9 |
10 | Change:
11 | - "Call Alert" is renamed to "SMS Alert"
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/112.txt:
--------------------------------------------------------------------------------
1 | change:
2 | "answer & hang up" now requires permission READ_CALL_LOG (required for getting incoming number)
3 |
4 | new:
5 | call/sms blocking can be enabled individually
6 |
7 | fix:
8 | wrong call block reason in notification
9 |
10 | improvement:
11 | backup/restore support compressing
12 | use shorter words for translations
13 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/116.txt:
--------------------------------------------------------------------------------
1 | Breaking:
2 | - After upgrading to this version, QuickCopy rules are updated, please backup again.
3 | Fix:
4 | - Rule notification icon missing in light theme
5 | Improvement:
6 | - QuickCopy supports copying phone number
7 | - Click history record to open the conversation in call/sms app
8 | - New theme type "follow system"(used by default)
9 | - Improved UI
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/117.txt:
--------------------------------------------------------------------------------
1 | Improvement:
2 | - "Backup & Restore" is now based on file. (using scoped storage, no permission required)
3 | - Improve performance for long rule
4 |
5 | New:
6 | - Import blacklist numbers from file by long pressing the "Add" button, it supports any files that have numbers in the first column.
7 |
8 | Fix:
9 | - Crash caused by unknown number
10 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/202.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - RecentApps: individual duration for each app
3 | - "Contact Group" mode in regex rule, making it easy to block all contacts in a group at once instead of blocking them individually
4 | - Context menu item "Delete duplicated rules"
5 | Fix:
6 | - UI frozen due to super long regex
7 | - rule count indicator in "delete all(%d) rules" never get updated
8 |
--------------------------------------------------------------------------------
/metadata/ru/full_description.txt:
--------------------------------------------------------------------------------
1 | Блокирует нежелательные звонки и SMS, не заменяя приложение для звонков/SMS по умолчанию.
2 |
3 | Фильтры:
4 |
5 | 1. Правила по регулярному выражению для номера и содержания SMS.
6 | 2. Контакты
7 | 3. Аттестация STIR
8 | 4. Повторный звонок
9 | 5. Набранный номер
10 | 6. Недавно использованные приложения
11 | 7. Расписание
12 |
13 | Подробности: https://github.com/aj3423/SpamBlocker
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/16.txt:
--------------------------------------------------------------------------------
1 | Breaking changes:
2 | - RepeatedCall/Dialed are now based on system call log instead of local db
3 | - Now it requires READ_CALL_LOG and READ_SMS for RepeatedCall/Dialed to work
4 |
5 | New features:
6 | - Permit calls from dialed number
7 | - Silence call
8 | - Backup & Restore
9 | - Off Time
10 |
11 | Improvements:
12 | - New app icon, thanks to nvllz
13 | - i18n - Chinese Simplified, thanks to yzqzss
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_right_arrow.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/420.txt:
--------------------------------------------------------------------------------
1 | Fix:
2 | - Backup import crashes with cloud files
3 | - "Hang Up" mode
4 | Automatically switch to "Reject" mode to avoid ending ongoing calls
5 |
6 | Enhancements:
7 | - Workflow:
8 | - New preset: FTC-DNC initial database (90-day historical data)
9 | - Report Number
10 | - When creating QueryApi, also create the corresponding ReportApi
11 | - Options for disabling auto reporting for NonContact/STIR/Regex
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/widgets/Form.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.widgets
2 |
3 | import androidx.compose.runtime.Composable
4 |
5 | data class FormField(val label: String, var value: String = "")
6 |
7 | @Composable
8 | fun FormInputField(formField: FormField) {
9 | StrInputBox(
10 | text = formField.value,
11 | onValueChange = { formField.value = it },
12 | label = { GreyLabel(formField.label) }
13 | )
14 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dropdown_arrow.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/401.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Call Alert, allow all calls after receiving some particular SMS messages, e.g.:
3 | > (from ...) We are calling you to inform ..., please feel free to answer.
4 |
5 | Fix:
6 | - Crash on incoming call or text that caused by complex regex patterns.
7 | - Crash when upgrading from ancient version.
8 |
9 | Improvement:
10 | - Test regex directly in the editing dialog, no more "increase priority + global testing".
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_time_slot.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/405.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - MMS support
3 | - Text content only, multimedia content is ignored.
4 | - Available in the top "Enable" setting dialog, disabled by default.
5 |
6 | Improvements:
7 | - Workflow
8 | - Added last run log in context menu
9 | - History log
10 | - Show multiple icons before the number to indicate if it exists in database/regex rule, ordered by priority, disabled by default
11 | - Language support:
12 | - Indonesian(in), thanks to @cyberboh
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sms.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sms_pass.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rTW/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 關閉簡訊應用程式的通知,
5 | 以避免重複通知。
6 |
7 | 如果簡訊應用程式強制要求通知權限,您可以保持授予該權限,
8 | 但改為關閉所有通知管道。
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/19.txt:
--------------------------------------------------------------------------------
1 | breaking:
2 | - SilenceCall is replaced with BlockType (reject / silence / answer & hang up)
3 | new:
4 | - new block type: Answer & Hang Up (to avoid being sent to voicemail)
5 | - time schedule per rule
6 | - block type per rule
7 | fix:
8 | - when the app is disabled, there is a 5 seconds delay before it starts ringing
9 | - language and STIR settings not backed up/restored
10 | - permit emergency call not work
11 | - QuickCopy trims leading 0 (code 0123 shown as "Copy: 123")
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/419.txt:
--------------------------------------------------------------------------------
1 | Fixes:
2 | - Workflow
3 | - CSV parser doesn't work with Windows line ending "\r\n"
4 | - Crash when removing the last workflow action
5 | - ModifyRules can't change rule priority
6 | - Report Number
7 | - Remove the priority for ReportApi, it shouldn't have priority.
8 |
9 | Enhancements:
10 | - Workflow
11 | - Http retry
12 | - Support customizing tags, useful for multi-step web queries.
13 |
14 | Language Support:
15 | - zh-rTW (thanks to @PeterDaveHello)
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # http://developer.android.com/guide/developing/tools/proguard.html
2 |
3 |
4 | # For backup/restore config
5 | # `keep` also keeps the class inner structure
6 | -keep class spam.blocker.config.* { *; }
7 |
8 | # For backup/restore permissions
9 | # `keepnames` only keeps the class name, this will generate `PermissionTypes$CallScreening`
10 | # in release mode, use `substringAfterLast('$')` to get rid of the `PermissionTypes$`.
11 | -keepnames class spam.blocker.util.PermissionType$** { *; }
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/500.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Multi SIM support (Android 12+)
3 | - New regex option: "SIM Card"
4 | Use case: block everything on SIM 1 and use only its data
5 |
6 | Fixes:
7 | - Workflow FTC-Initial doesn't work on Android 10/11
8 | - MMS doesn't work with Google Messages being the SMS app
9 | - File picker shows ghost files that can't be imported
10 |
11 | Improvements:
12 | - Regex presets
13 | - Time tags with arithmetic operations, such as `{day-1}`
14 | Use case: download last 3 days' numbers from FTC-DNC
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sim_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/Clipboard.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.util
2 |
3 | import android.content.ClipData
4 | import android.content.ClipboardManager
5 | import android.content.Context
6 |
7 | class Clipboard {
8 | companion object {
9 | fun copy(ctx: Context, toCopy: String?) {
10 | val clipboardManager = ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
11 | val clipData = ClipData.newPlainText("", toCopy)
12 | clipboardManager.setPrimaryClip(clipData)
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 关闭短信应用的通知
5 | 以避免双重通知。
6 |
7 | 如果短信应用强制要求通知权限,您可以保持授予该权限
8 | 并改为关闭所有通知渠道。
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ja/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | SMSアプリの通知をオフにしてください。
5 |
6 | SMSアプリが通知権限を強制する場合でも、権限は許可したまま、代わりにすべての通知チャンネルをオフにすることができます。
7 | ]]>
8 |
9 |
10 |
12 |
13 | %s
14 | ]]>
15 |
16 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/303.txt:
--------------------------------------------------------------------------------
1 | Fix:
2 |
3 | - RepeatedCall/Dialed fail to identify international and domestic numbers belonging to the same person. Thanks to @lbschenkel for the PR.
4 | The permission READ_PHONE_STATE is necessary for this to work. (it's optional)
5 | - History record not showing full date for old records
6 |
7 | Improvement:
8 |
9 | - Show execution coundown in the workflow context menu.
10 | - Expand/Collapse workflow list by clicking the header
11 | - New options for action "Import as Regex Rule": Create/Replace/Merge and Blacklist/Whitelist
12 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/MockkWorkaround.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.util
2 |
3 | import java.time.LocalDateTime
4 |
5 | // This file contains wrappers for testing, mockk doesn't support hooking
6 | // `System.currentTimeMillis()` or `LocalDateTime.now()`
7 |
8 | open class Now {
9 | companion object {
10 |
11 | fun currentMillis(): Long {
12 | return System.currentTimeMillis()
13 | }
14 | }
15 | }
16 |
17 | object LocalDateTimeMockk {
18 | fun now() : LocalDateTime {
19 | return LocalDateTime.now()
20 | }
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_http_header.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_toggle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/120.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - adapt android 15, changes:
3 | - the top bar no longer shows green/red to indicate enabled or not
4 | - "Delete All Rules" context menu item
5 |
6 | Fix:
7 | - no more ghost process that always redirects to the sms app
8 |
9 | Enhancement:
10 | - testing now works with RepeatedCall, it also checks local db(only when testing)
11 | - red indicator for swiping left
12 | - Import rules from csv:
13 | - use filename as description
14 | - show warning when the .csv doesn't contain the required column "pattern", to prevent empty rows
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sms_blocked.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/200.txt:
--------------------------------------------------------------------------------
1 | The UI has been completely re-written with jetpack compose.
2 |
3 | Fix:
4 | - Crash caused by some mysterious contact image.
5 | - Crash caused by rotating screen.
6 | - Wrong contact image.
7 | - Some settings not backed up:
8 | - show passed
9 | - show blocked
10 |
11 | New:
12 | - Show SMS detail:
13 | A new switch "Log SMS Content" in the SMS tab. When enabled, SMS message will be logged in local database and displayed in the history record. Disabled by default.
14 |
15 | Changes:
16 | - 3 testing buttons are replaced by a floating button.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/4.share.yml:
--------------------------------------------------------------------------------
1 | name: Share Regex/Workflow
2 | description: Share your regex rules or workflows
3 | title: "[Country] Description"
4 | labels: [share regex/workflow]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Thanks for sharing, the content will be synchronized to the wiki page within a minute.
10 | If you need to update the content later, just edit this issue.
11 |
12 | - type: textarea
13 | id: detail
14 | attributes:
15 | label: "The regex/workflow"
16 | validations:
17 | required: true
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contact_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_question.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_reorder.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_priority.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/416.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Workflow
3 | - Call Throttling
4 | - Block consecutive spam calls that bypass all rules.
5 | - SMS Throttling
6 | - Allow first N SMS notifications and mute the rest for a period.
7 |
8 | Fix:
9 | - Priority inputbox typing issue
10 | - Workflow action "Find Rules" doesn't work in some cases
11 |
12 | Enhancements:
13 | - API query
14 | - Support mapping the result to human readable text, e.g.:
15 | "1" -> "Fraud", "2" -> "Advertising"
16 |
17 | Changes:
18 | - Regex flags
19 | - "Ignore Case" is changed to "Case Sensitive" (logic negated)
20 | - "Dot Match All" is removed
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | breaking change:
2 | - leading zeroes in numbers are removed before checking
3 |
4 | new feature:
5 | - Quick Copy: copy verification code from notification
6 |
7 | enhancement:
8 | - priority for Contact/repeated/RecentApp
9 | - regex options, IgnoreCase, DotMatchAll by default
10 | - inclusive/exclusive contact mode
11 | - rule clone
12 |
13 | change:
14 | - clicking notifications opens default call/SMS app
15 | - better notificaton icon
16 |
17 | fix:
18 | - enterprise numbers like "Microsoft"
19 | - domestic trunk prefix(leading '0's)
20 | - rename notification channels: `Shade`, `Shade+Sound`...
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/widgets/GreenDot.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.widgets
2 |
3 | import androidx.compose.foundation.Canvas
4 | import androidx.compose.foundation.layout.size
5 | import androidx.compose.runtime.Composable
6 | import androidx.compose.ui.Modifier
7 | import androidx.compose.ui.graphics.Color
8 | import androidx.compose.ui.unit.dp
9 |
10 | // The green dot in BotCard and ApiCard, indicating the bot is scheduled or the api is enabled.
11 | @Composable
12 | fun GreenDot() {
13 | Canvas(
14 | modifier = Modifier.size(6.dp)
15 | ) {
16 | drawCircle(color = Color.Green, radius = size.minDimension / 2)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_duration.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/setting/misc/Logcat.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.setting.misc
2 |
3 | import java.io.BufferedReader
4 | import java.io.InputStreamReader
5 |
6 | object Logcat {
7 | fun collect(): String {
8 | val process = Runtime.getRuntime().exec("logcat -d")
9 | val reader = BufferedReader(InputStreamReader(process.inputStream))
10 | val logBuilder = StringBuilder()
11 | var line: String?
12 |
13 | while (reader.readLine().also { line = it } != null) {
14 | logBuilder.append(line).append("\n")
15 | }
16 | reader.close()
17 |
18 | return logBuilder.toString()
19 | }
20 | }
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/305.txt:
--------------------------------------------------------------------------------
1 | Fixes:
2 | - android 15 tooltip truncated
3 | - rule "Save" button is always disabled under certain conditions
4 |
5 | Improvements:
6 | - swipe left to dismiss the snackbar
7 | - "Mark all as read" for history records
8 | - new workflow actions:
9 | - "Enable App" and "Enable Workflow"
10 | - use case: temporarily disable the app and auto re-enable it after 1 hour
11 | - "Find Rules" and "Modify Rules"
12 | - use case: temporarily disable/enable multiple rules
13 | - support more .csv separators: , ; |
14 |
15 | Changes:
16 | - Tapping a history record will only mark it as read, swipe right to open the conversation in the default app.
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_call.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_fail_red.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_flags.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-tr/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | SMS uygulamasının bildirimini kapattığınızdan emin olun.
5 |
6 | SMS uygulaması bildirim izni zorluyorsa, izni açık bırakabilir ve bunun yerine tüm bildirim kanallarını kapatabilirsiniz.
7 | ]]>
8 |
9 |
10 |
12 |
13 | %s
14 | ]]>
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_repeat.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ar/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | إيقاف إشعارات تطبيق الرسائل القصيرة في إعدادات النظام لتجنب الإشعارات المزدوجة.
5 |
6 | إذا كان تطبيق الرسائل القصيرة يفرض إذن الإشعارات، يمكنك إبقائه ممنوحًا وإيقاف تشغيل قنوات الإشعارات كلها بدلاً من ذلك.
7 | ]]>
8 |
9 |
10 |
12 |
13 | %s
14 | ]]>
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-iw/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | לכבות את ההתראות של אפליקציית ההודעות בהגדרות המערכת
5 | כדי למנוע כפילויות בהתראות.
6 |
7 | אם אפליקציית ההודעות אוכפת הרשאת התראות, באפשרותך להשאיר אותה מוענקת
8 | ולכבות את כל ערוצי ההתראות במקום זאת.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | mavenCentral()
4 | maven { url = uri("https://jitpack.io") }
5 | google {
6 | content {
7 | includeGroupByRegex("com\\.android.*")
8 | includeGroupByRegex("com\\.google.*")
9 | includeGroupByRegex("androidx.*")
10 | }
11 | }
12 | gradlePluginPortal()
13 | }
14 | }
15 | dependencyResolutionManagement {
16 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
17 | repositories {
18 | mavenCentral()
19 | maven { url = uri("https://jitpack.io") }
20 | google()
21 | }
22 | }
23 |
24 | rootProject.name = "SpamBlocker"
25 | include(":app")
26 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_copy.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_http.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_number_sign.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bell_mute.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | turn off the SMS app\'s notification in system settings
5 | to avoid double notifications.
6 |
7 | If the SMS app enforces notification permission, you can keep it granted
8 | and turn off all notification channels instead.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/404.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - SMS API query
3 | - Identify SMS using AI, preset: Google Gemini
4 |
5 | Fix:
6 | - SMS regex rule can't be disabled
7 |
8 | Improvements:
9 | - Language support: Persian(fa)
10 | - PhoneBlock API
11 | - Query by hash for better privacy.
12 | The number's SHA1 hash will be sent to the server rather than the number itself.
13 | E.g.: query *DF439FA74E14A336F06E2BEE6C26085DA438005C* instead of *+331234567890*.
14 | To apply this, delete existing configuration and recreate it.
15 | - It now uses API key instead of username/password.
16 | - History log:
17 | - Show a red indicator when the number exists in the spam database.
18 | - Menu "Add number to database" becomes "Delete from database" when it already exists.
19 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/415.txt:
--------------------------------------------------------------------------------
1 | Please re-backup.
2 |
3 | Breaking change:
4 | - STIR Lenient mode is removed.
5 | The new "Lenient" label means "don't block unverified call".
6 |
7 | New:
8 | - Customizable notification:
9 | icon, color, sound, LED, grouping
10 | - Workflow trigger: "Call Event"
11 | Run a workflow on incoming call.
12 | Use case: remove number prefix for "1 SIM card dual numbers"
13 |
14 | Fix:
15 | - RepeatedCall/AnsweredNumber, crash that caused by "private" number.
16 | - It asks for wrong permissions after restoring.
17 | - History indicator ignores "for particular number".
18 |
19 | Improvement:
20 | - Workflow actions File Read/Write now support date tags, such as `{day_of_week}`.
21 | Use case: Do a daily backup and only keep last 7 backups.
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values-fa/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | اعلان برنامه پیامک را خاموش کنید در تنظیمات سیستم
5 | تا از اعلانهای دوگانه جلوگیری کنید.
6 |
7 | اگر برنامه پیامک مجوز اعلان را اجباری میکند، میتوانید آن را اعطا شده نگه دارید
8 | و در عوض، همه کانالهای اعلان را خاموش کنید.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_clear.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-in/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | mematikan notifikasi aplikasi SMS di pengaturan sistem
5 | untuk menghindari notifikasi ganda.
6 |
7 | Jika aplikasi SMS memberlakukan izin notifikasi, Anda dapat tetap memberikannya
8 | dan mematikan semua saluran notifikasi sebagai gantinya.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values-it/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | disattivare le notifiche dell\'app SMS nelle impostazioni di sistema
5 | per evitare doppie notifiche.
6 |
7 | Se l\'app SMS impone l\'autorizzazione alle notifiche, puoi mantenerla concessa
8 | e disattivare invece tutti i canali di notifica.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_note.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | отключите уведомления приложения SMS в системных настройках,
5 | чтобы избежать двойных уведомлений.
6 |
7 | Если приложение SMS требует разрешение на уведомления, вы можете оставить его предоставленным
8 | и отключить все каналы уведомлений.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values-uk/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | вимкнули сповіщення програми SMS у системних налаштуваннях,
5 | щоб уникнути подвійних сповіщень.
6 |
7 | Якщо програма SMS примусово вимагає дозволу на сповіщення, ви можете залишити його наданим
8 | і замість цього вимкнути всі канали сповіщень.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_filter.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values-gal/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | desactivar as notificacións da aplicación de SMS na configuración do sistema
5 | para evitar notificacións dobres.
6 |
7 | Se a aplicación de SMS forza o permiso de notificación, podes mantelo concedido
8 | e desactivar todas as canles de notificación no seu lugar.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_flag_catalan.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_unknown_app_icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pt-rBR/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | desativar a notificação do aplicativo de SMS nas configurações do sistema
5 | para evitar notificações duplicadas.
6 |
7 | Se o aplicativo de SMS impõe a permissão de notificação, você pode mantê-la concedida
8 | e desativar todos os canais de notificação em vez disso.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values-es/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | desactivar las notificaciones de la aplicación de SMS en la configuración del sistema
5 | para evitar notificaciones duplicadas.
6 |
7 | Si la aplicación de SMS exige el permiso de notificación, puedes mantenerlo concedido
8 | y desactivar todos los canales de notificación en su lugar.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ca/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | desactivar les notificacions de l\'aplicació de SMS a la configuració del sistema
5 | per evitar notificacions duplicades.
6 |
7 | Si l\'aplicació de SMS exigeix permís de notificació, pots mantenir-lo concedit
8 | i desactivar tots els canals de notificació en el seu lloc.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_weekly.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values-de/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | die Benachrichtigungen der SMS-App in den Systemeinstellungen deaktivieren,
5 | um doppelte Benachrichtigungen zu vermeiden.
6 |
7 | Wenn die SMS-App eine Benachrichtigungsberechtigung erzwingt, können Sie diese gewährt lassen
8 | und stattdessen alle Benachrichtigungskanäle deaktivieren.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values-fr/strings_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | désactiver les notifications de l\'application SMS dans les paramètres système
5 | pour éviter les doubles notifications.
6 |
7 | Si l\'application SMS impose une autorisation de notification, vous pouvez la laisser accordée
8 | et désactiver plutôt tous les canaux de notification.
9 | ]]>
10 |
11 |
12 |
15 |
16 | %s
17 | ]]>
18 |
19 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/414.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Feature "Answered Numbers"
3 | Allow calls that recently answered.
4 |
5 | Fix:
6 | - App crash when receiving MMS without text content
7 | - SMS rules cannot be disabled
8 |
9 | Improvements:
10 | - Customizable priority for "Contacts", "STIR" and "Instant Query"
11 | - Use case:
12 | Always allow contacts and block calls that fail STIR or are marked as spam by API, even if they repeat.
13 | Contacts(priority 13), STIR/Strict(12), InstantQuery(11) RepeatedCall(10)
14 | - Prompt to grant all previous permissions after backup restore.
15 | (applies only to new backup files)
16 | - New option "Include SMS" for "Dialed Number" and "Repeated Call"
17 | (previously hardcoded and cannot be disabled)
18 | - Valid SMS notifications are grouped together.
19 |
20 | Changes:
21 | - "Inclusive/Exclusive" are now "Lenient/Strict".
22 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/service/Tile.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.service
2 |
3 | import android.service.quicksettings.Tile.STATE_ACTIVE
4 | import android.service.quicksettings.Tile.STATE_INACTIVE
5 | import android.service.quicksettings.TileService
6 | import spam.blocker.G
7 | import spam.blocker.util.spf
8 |
9 | class Tile : TileService() {
10 |
11 | private fun update() {
12 | val spf = spf.Global(this)
13 | val enabled = spf.isGloballyEnabled()
14 | qsTile.state = if (enabled) STATE_ACTIVE else STATE_INACTIVE
15 |
16 | qsTile.updateTile()
17 | }
18 | override fun onStartListening() {
19 | update()
20 | }
21 |
22 | override fun onClick() {
23 | val spf = spf.Global(this)
24 | spf.toggleGloballyEnabled()
25 |
26 | update()
27 |
28 | G.globallyEnabled.value = spf.isGloballyEnabled()
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_find.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/304.txt:
--------------------------------------------------------------------------------
1 | New:
2 | - Meeting Mode, auto decline calls during online video conferences
3 | - language support: Turkish(tr), thanks to @parduspanteri
4 |
5 | Fix:
6 | - "include spam database" switch not toggled on tapping
7 | - when adding a rule, the error text is not refreshed on flags change
8 |
9 | Improvement:
10 | - upgrade translation engine from gemini v1.0 to v1.5, improving translation quality
11 | - for languages that have long text, widgets will wrap to the next line if there's insufficient space left
12 | - configurable "initial sms row count" in sms history
13 | - new history context menu item "add number to spam db"
14 | - search/delete number in spam db
15 | - customizable http header for HttpDownload
16 | - support clear-text HttpDownload
17 | - rule list options: max display lines for the regex/description, max list height
18 | - import SMS rules from .csv
19 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/service/CopyToClipboardReceiver.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.service
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 | import spam.blocker.util.Clipboard
7 | import spam.blocker.util.Notification
8 |
9 | class CopyToClipboardReceiver : BroadcastReceiver() {
10 | override fun onReceive(ctx: Context, intent: Intent) {
11 |
12 | // dismiss this notification, others remain
13 | val notifId = intent.getIntExtra("notificationId", 0)
14 | Notification.cancelById(ctx, notifId)
15 |
16 | // copy to clipboard
17 | val toCopy = intent.getStringExtra("toCopy")
18 | Clipboard.copy(ctx, toCopy)
19 |
20 | // val copied = ctx.getString(R.string.copied_to_clipboard)
21 | // Toast.makeText(ctx, copied.format(toCopy), Toast.LENGTH_SHORT).show();
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_regex.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
12 |
17 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_heads_up.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_workflow.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_no.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.theme
2 |
3 | import androidx.compose.material3.Typography
4 |
5 | // Set of Material typography styles to start with
6 | val Typography = Typography(
7 | // bodyLarge = TextStyle(
8 | // fontFamily = FontFamily.Default,
9 | // fontWeight = FontWeight.SemiBold,
10 | // fontSize = 24.sp,
11 | // lineHeight = 24.sp,
12 | // letterSpacing = 0.5.sp
13 | // )
14 | /* Other default text styles to override
15 | titleLarge = TextStyle(
16 | fontFamily = FontFamily.Default,
17 | fontWeight = FontWeight.Normal,
18 | fontSize = 22.sp,
19 | lineHeight = 28.sp,
20 | letterSpacing = 0.sp
21 | ),
22 | labelSmall = TextStyle(
23 | fontFamily = FontFamily.Default,
24 | fontWeight = FontWeight.Medium,
25 | fontSize = 11.sp,
26 | lineHeight = 16.sp,
27 | letterSpacing = 0.5.sp
28 | )
29 | */
30 | )
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_statusbar_shade.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
15 |
16 |
19 |
22 |
25 |
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1.bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Report an issue
3 | labels: [bug]
4 | body:
5 |
6 | - type: checkboxes
7 | attributes:
8 | label: "Please search first"
9 | options:
10 | - label: "I have searched and there are no duplicates"
11 | required: true
12 |
13 | - type: input
14 | id: SpamBlocker-version
15 | attributes:
16 | label: SpamBlocker version
17 | description: |
18 | You can find the version in the **About** dialog.
19 | placeholder: |
20 | Example: 4.21
21 | validations:
22 | required: false
23 |
24 | - type: input
25 | id: android-version
26 | attributes:
27 | label: Android version
28 | placeholder: |
29 | Example: 15
30 | validations:
31 | required: true
32 |
33 |
34 | - type: textarea
35 | id: detail
36 | attributes:
37 | label: The issue
38 | validations:
39 | required: true
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_yes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/300.txt:
--------------------------------------------------------------------------------
1 | Breaking:
2 | - no longer support "export backup as json format"
3 | - New permissions:
4 | - INTERNET: for downloading spam database, you can [disable it](https://github.com/aj3423/SpamBlocker/issues/147) if you don't use this feature.
5 | - MANAGE_EXTERNAL_STORAGE(Android 11+) or READ/WRITE_EXTERNAL_STORAGE(Android 10), for automated file operations, such as "backup" or "import .csv".
6 |
7 | New:
8 | - Spam Database. It's compatible with any public data sources, such as the [FTC - DNC](ftc.gov/policy-notices/open-government/data-sets/do-not-call-data)
9 | - Automated workflow. Use cases:
10 | - Download spam numbers from public database everyday.
11 | - Clean up expired numbers in database.
12 | - Auto backup, auto switch configuration, auto import csv/xml, etc.
13 | - Regex contact mode. The regex will match the contact name instead of the phone number
14 | - language support: pt-rBR, ja
15 |
16 | Fix:
17 | - The history cleanup task is not applied after backup-import
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_category.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_file_read.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_hourglass.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_incoming.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contact_square.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/setting/bot/BotViewModel.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.setting.bot
2 |
3 | import android.content.Context
4 | import androidx.compose.runtime.mutableStateListOf
5 | import androidx.compose.runtime.mutableStateOf
6 | import spam.blocker.db.Bot
7 | import spam.blocker.db.BotTable
8 | import spam.blocker.util.spf
9 |
10 | class BotViewModel {
11 | val bots = mutableStateListOf()
12 | val listCollapsed = mutableStateOf(false)
13 |
14 |
15 | fun reload(ctx: Context) {
16 | bots.clear()
17 |
18 | val all = BotTable.listAll(ctx)
19 | bots.addAll(all)
20 |
21 | listCollapsed.value = spf.BotOptions(ctx).isListCollapsed()
22 | }
23 |
24 | fun toggleCollapse(ctx: Context) {
25 | // don't collapse if it's empty
26 | if (bots.isEmpty() && !listCollapsed.value) {
27 | return
28 | }
29 |
30 | listCollapsed.value = !listCollapsed.value
31 | spf.BotOptions(ctx).setListCollapsed(listCollapsed.value)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/metadata/en-US/changelogs/413.txt:
--------------------------------------------------------------------------------
1 | Fix:
2 | - App hangs at startup. (on some devices)
3 |
4 | Help wanted:
5 | - On some devices, calls are always allowed, the app doesn't work at all.
6 | If you are experiencing this issue, please check:
7 | https://github.com/aj3423/SpamBlocker/issues/362#issuecomment-3016385834
8 |
9 | New:
10 | - Workflow actions:
11 | - Calendar Event
12 | On incoming calls, temporarily adjust rules according to ongoing calendar events.
13 | - Use case:
14 | Someone works 7AM-10AM for two days, then 2PM-5PM for the next two,
15 | some rules need to be disabled during those working hours.
16 | - SMS Event
17 | An action that will be triggered on incoming SMS messages.
18 | - Use case:
19 | For shift workers that receive oncall/offcall SMS notifications,
20 | this can help to toggle rules automatically.
21 |
22 | Improvements:
23 | - Spam Database
24 | - Customizable priority
25 | - Quick Copy
26 | - "Auto Copy" to clipboard (optional)
27 |
28 | Language support:
29 | - Hebrew (iw)
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contact_group.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_history_cleanup.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/setting/bot/EditActionDialog.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.setting.bot
2 |
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.runtime.MutableState
5 | import androidx.compose.runtime.mutableStateOf
6 | import androidx.compose.runtime.remember
7 | import spam.blocker.service.bot.IAction
8 | import spam.blocker.service.bot.parseAction
9 | import spam.blocker.service.bot.serialize
10 | import spam.blocker.ui.widgets.PopupDialog
11 | import spam.blocker.util.Lambda1
12 |
13 | // when this dialog closes, the actions[i] will be updated
14 | @Composable
15 | fun EditActionDialog(
16 | trigger: MutableState,
17 | initial: IAction,
18 | callback: Lambda1,
19 | ) {
20 | val edited = remember(initial) { mutableStateOf(initial) }
21 |
22 | PopupDialog(
23 | trigger = trigger,
24 | onDismiss = {
25 | // set to itself to refresh the UI
26 | val clone = edited.value.serialize().parseAction()
27 | callback(clone)
28 | }
29 | ) {
30 | edited.value.Options()
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/Flag.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.util
2 |
3 | import spam.blocker.def.Def
4 |
5 | // check if it has a flag
6 | fun Int.hasFlag(f: Int): Boolean {
7 | return this and f == f
8 | }
9 |
10 | // add or remove a flag
11 | fun Int.setFlag(f: Int, enabled: Boolean): Int {
12 | return if (enabled) { // add flag
13 | this or f
14 | } else { // clear flag
15 | this and f.inv()
16 | }
17 | }
18 | fun Int.addFlag(f: Int): Int {
19 | return setFlag(f, true)
20 | }
21 | fun Int.removeFlag(f: Int): Int {
22 | return setFlag(f, false)
23 | }
24 |
25 | // Generate string "imdlc" from flags
26 | // params:
27 | // attrMap - mapOf(IgnoreCase -> "i", DotMatchAll -> "d", ...)
28 | // inverse - invert the showing behavior of some flags,
29 | // by default it's: show when set
30 | // if it's inverted: show when not set
31 | fun Int.toFlagStr(
32 | attrMap: Map = Def.MAP_REGEX_FLAGS,
33 | ): String {
34 | var ret = ""
35 | attrMap.forEach { (k, v) ->
36 | if (hasFlag(k))
37 | ret += v
38 | }
39 | return ret
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delay.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_calendar.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 aj3423
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_recycle_bin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/service/CustomTile.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.service
2 |
3 | import android.service.quicksettings.Tile.STATE_ACTIVE
4 | import android.service.quicksettings.Tile.STATE_INACTIVE
5 | import android.service.quicksettings.TileService
6 | import androidx.compose.runtime.MutableState
7 | import spam.blocker.G
8 | import spam.blocker.util.spf
9 |
10 | open class CustomTileBase(
11 | val state: MutableState,
12 | val tileIndex: Int, // 1, 2, ...
13 | ) : TileService() {
14 |
15 | private fun update() {
16 | val spf = spf.BotOptions(this)
17 | val enabled = spf.isDynamicTileEnabled(tileIndex)
18 | qsTile.state = if (enabled) STATE_ACTIVE else STATE_INACTIVE
19 |
20 | qsTile.updateTile()
21 | }
22 | override fun onStartListening() {
23 | update()
24 | }
25 |
26 | override fun onClick() {
27 | val spf = spf.BotOptions(this)
28 |
29 | val enabled = spf.isDynamicTileEnabled(tileIndex)
30 | spf.setDynamicTileEnabled(tileIndex, !enabled) // toggle
31 |
32 | update()
33 |
34 | state.value = !enabled
35 | }
36 | }
37 |
38 | class CustomTile : CustomTileBase(G.dynamicTile0Enabled, 0)
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mms.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/.github/workflows/labeler.yml:
--------------------------------------------------------------------------------
1 | # Made with love
2 | #
3 | # This workflow uses actions that are not certified by GitHub.
4 | #
5 | # They are provided by a third-party and are governed by
6 | # separate terms of service, privacy policy, and support
7 | # documentation.
8 | # see https://github.com/actions/labeler
9 | # for more informations
10 | #
11 | # For most projects, this workflow file will not need changing; you simply need:
12 | # 1 - commit this file to your repository into the '.github/workflows' folder.
13 | # 2 - commit the 'labeler.yml' configuration file into the '.github' folder.
14 | #
15 | # You probably want to add, replace or delete labels,
16 | # remember to check this configuration file.
17 | #
18 |
19 | name: "Pull Request Labeler"
20 | on:
21 | - pull_request_target
22 |
23 | jobs:
24 | triage:
25 | permissions:
26 | contents: read
27 | pull-requests: write
28 | runs-on: ubuntu-latest
29 | steps:
30 | - uses: actions/labeler@v5
31 | with:
32 | # Check if you have enabled tokens for your repository
33 | repo-token: "${{ secrets.GITHUB_TOKEN }}"
34 | # This removes the label if the change(s) are undone in the PR
35 | sync-labels: true
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/widgets/OutlinedCard.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.widgets
2 |
3 | import androidx.compose.foundation.BorderStroke
4 | import androidx.compose.foundation.shape.RoundedCornerShape
5 | import androidx.compose.material3.CardDefaults
6 | import androidx.compose.material3.MaterialTheme
7 | import androidx.compose.material3.OutlinedCard
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Modifier
10 | import androidx.compose.ui.graphics.Color
11 | import androidx.compose.ui.unit.dp
12 | import spam.blocker.ui.theme.LocalPalette
13 |
14 | @Composable
15 | fun OutlineCard(
16 | modifier: Modifier = Modifier,
17 | containerBg: Color = MaterialTheme.colorScheme.background,
18 | content: @Composable () -> Unit,
19 | ) {
20 | val C = LocalPalette.current
21 |
22 | OutlinedCard(
23 | modifier = modifier,
24 | colors = CardDefaults.cardColors(
25 | containerColor = containerBg,
26 | ),
27 | border = BorderStroke(width = 1.dp, color = C.cardBorder),
28 | shape = RoundedCornerShape(6.dp),
29 | elevation = CardDefaults.cardElevation(defaultElevation = 0.dp),
30 | ) {
31 | content()
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/widgets/Animation.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.widgets
2 |
3 | import androidx.compose.animation.AnimatedVisibility
4 | import androidx.compose.animation.expandVertically
5 | import androidx.compose.animation.shrinkVertically
6 | import androidx.compose.runtime.Composable
7 |
8 | //@Composable
9 | //fun AnimateVisibleH(
10 | // visible: Boolean,
11 | // content: @Composable ()->Unit
12 | //) {
13 | // AnimatedVisibility(
14 | // visible = visible,
15 | // enter = expandHorizontally(
16 | // animationSpec = tween(durationMillis = 300),
17 | // expandFrom = Alignment.Start
18 | // ) + fadeIn(),
19 | // exit = shrinkHorizontally(
20 | // animationSpec = tween(durationMillis = 300),
21 | // shrinkTowards = Alignment.Start
22 | // ) + fadeOut()
23 | // ) {
24 | // content()
25 | // }
26 | //}
27 |
28 | @Composable
29 | fun AnimatedVisibleV(
30 | visible: Boolean,
31 | content: @Composable () -> Unit,
32 | ) {
33 | AnimatedVisibility(
34 | visible = visible,
35 | enter = expandVertically(),
36 | exit = shrinkVertically()
37 | ) {
38 | content()
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_file_write.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_green.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/history/HistoryViewModel.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.history
2 |
3 | import android.content.Context
4 | import androidx.compose.runtime.mutableStateListOf
5 | import androidx.lifecycle.ViewModel
6 | import spam.blocker.db.CallTable
7 | import spam.blocker.db.HistoryRecord
8 | import spam.blocker.db.HistoryTable
9 | import spam.blocker.db.SmsTable
10 | import spam.blocker.def.Def
11 | import spam.blocker.util.spf
12 |
13 | /*
14 | To simplify the code, this view model is used in GlobalVariables instead of viewModel<...>().
15 | */
16 | open class HistoryViewModel(
17 | val forType: Int,
18 | val table: HistoryTable,
19 | ) : ViewModel() {
20 | val records = mutableStateListOf()
21 |
22 | fun reload(ctx: Context) {
23 | records.clear()
24 |
25 | val spf = spf.HistoryOptions(ctx)
26 | val showPassed = spf.getShowPassed()
27 | val showBlocked = spf.getShowBlocked()
28 |
29 | records.addAll(table.listRecords(ctx).filter {
30 | (showPassed && it.isNotBlocked()) || (showBlocked && it.isBlocked())
31 | })
32 | }
33 | }
34 |
35 | class CallViewModel : HistoryViewModel(Def.ForNumber, CallTable())
36 |
37 | class SmsViewModel : HistoryViewModel(Def.ForSms, SmsTable())
38 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_backup_import.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_link.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_call_miss.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/widgets/NonLazyGrid.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.widgets
2 |
3 | import androidx.compose.foundation.layout.Box
4 | import androidx.compose.foundation.layout.Column
5 | import androidx.compose.foundation.layout.Row
6 | import androidx.compose.runtime.Composable
7 | import androidx.compose.ui.Modifier
8 |
9 |
10 | // For the Bot icons.
11 | // LazyGrid can't be used in scrollable.
12 | // source: https://dev.to/maaxgr/jetpack-compose-grid-without-lazy-5gb8
13 | @Composable
14 | fun NonLazyGrid(
15 | columns: Int,
16 | itemCount: Int,
17 | modifier: Modifier = Modifier,
18 | content: @Composable() (Int) -> Unit
19 | ) {
20 | Column(modifier = modifier) {
21 | var rows = (itemCount / columns)
22 | if (itemCount.mod(columns) > 0) {
23 | rows += 1
24 | }
25 |
26 | for (rowId in 0 until rows) {
27 | val firstIndex = rowId * columns
28 |
29 | Row {
30 | for (columnId in 0 until columns) {
31 | val index = firstIndex + columnId
32 | Box {
33 | if (index < itemCount) {
34 | content(index)
35 | }
36 | }
37 | }
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_music.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/setting/misc/Theme.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.setting.misc
2 |
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.runtime.remember
5 | import androidx.compose.ui.platform.LocalContext
6 | import spam.blocker.G
7 | import spam.blocker.R
8 | import spam.blocker.ui.setting.LabeledRow
9 | import spam.blocker.ui.widgets.ComboBox
10 | import spam.blocker.ui.widgets.LabelItem
11 | import spam.blocker.util.spf
12 |
13 | @Composable
14 | fun Theme() {
15 | val ctx = LocalContext.current
16 | val spf = spf.Global(ctx)
17 |
18 | val options = remember {
19 |
20 | val followSystem = ctx.resources.getString(R.string.follow_system)
21 | val themes = listOf(followSystem) + ctx.resources.getStringArray(R.array.theme_list).toList()
22 |
23 | themes.mapIndexed { index, label ->
24 | LabelItem(
25 | label = label,
26 | onClick = {
27 | spf.setThemeType(index)
28 | G.themeType.intValue = index
29 | }
30 | )
31 | }
32 | }
33 |
34 |
35 | LabeledRow(
36 | R.string.theme,
37 | content = {
38 | ComboBox(
39 | options,
40 | G.themeType.intValue,
41 | )
42 | }
43 | )
44 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bell_ringing.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_daily.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tag.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_xml.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_backup_export.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
29 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/widgets/SnackBar.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.widgets
2 |
3 | import androidx.compose.material3.SnackbarDuration
4 | import androidx.compose.material3.SnackbarHostState
5 | import androidx.compose.material3.SnackbarResult
6 | import kotlinx.coroutines.CoroutineScope
7 | import kotlinx.coroutines.Dispatchers.IO
8 | import kotlinx.coroutines.launch
9 | import kotlinx.coroutines.withContext
10 | import spam.blocker.util.Lambda
11 |
12 | object SnackBar {
13 | val state = SnackbarHostState()
14 |
15 | fun show(
16 | coroutine: CoroutineScope,
17 | content: String,
18 | actionLabel: String,
19 | onAction: Lambda
20 | ) {
21 | coroutine.launch {
22 | withContext(IO) {
23 | // cancel previous
24 | dismiss()
25 |
26 | val result = state.showSnackbar(
27 | if (content.length > 50) content.substring(0, 50) + "…" else content,
28 | actionLabel,
29 | withDismissAction = false,
30 | duration = SnackbarDuration.Short
31 | )
32 | if (result == SnackbarResult.ActionPerformed) {
33 | onAction()
34 | }
35 | }
36 | }
37 | }
38 | fun dismiss() {
39 | state.currentSnackbarData?.dismiss()
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tile.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. For more details, visit
12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/NotificationTrampolineActivity.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import spam.blocker.util.Launcher
6 | import spam.blocker.util.Notification
7 |
8 | class NotificationTrampolineActivity : ComponentActivity() {
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 |
12 | val type = intent!!.getStringExtra("type")
13 | val blocked = intent.getBooleanExtra("blocked", false)
14 |
15 | // val action = intent.action
16 | // logi("notification clicked, type: $type, blocked: $blocked, action: $action")
17 |
18 | when (type) {
19 | "sms" -> {
20 | if (blocked) { // launch the default SMS app
21 | Launcher.launchSMSApp(this)
22 | } else { // open the conversation in SMS app
23 | val smsTo = intent.getStringExtra("rawNumber")
24 | Launcher.openSMSConversation(this, smsTo)
25 | }
26 | }
27 | "call" -> { // only blocked calls have notification
28 | Launcher.launchCallApp(this)
29 | }
30 | else -> { // this should never happen
31 | Launcher.launchThisApp(this)
32 | }
33 | }
34 |
35 | Notification.cancelAll(this)
36 |
37 | finish()
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tube.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/pdu/util/PduCacheEntry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 Esmertec AG.
3 | * Copyright (C) 2008 The Android Open Source Project
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package spam.blocker.util.pdu.util;
19 |
20 |
21 | import spam.blocker.util.pdu.pdu.GenericPdu;
22 |
23 | public final class PduCacheEntry {
24 | private final GenericPdu mPdu;
25 | private final int mMessageBox;
26 | private final long mThreadId;
27 |
28 | public PduCacheEntry(GenericPdu pdu, int msgBox, long threadId) {
29 | mPdu = pdu;
30 | mMessageBox = msgBox;
31 | mThreadId = threadId;
32 | }
33 |
34 | public GenericPdu getPdu() {
35 | return mPdu;
36 | }
37 |
38 | public int getMessageBox() {
39 | return mMessageBox;
40 | }
41 |
42 | public long getThreadId() {
43 | return mThreadId;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/auto_translate/retry.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | )
7 |
8 | type RetryableError struct {
9 | Err error
10 | }
11 |
12 | func (e *RetryableError) Error() string {
13 | return e.Err.Error()
14 | }
15 |
16 | var retryableErr *RetryableError
17 |
18 | // ---- global func ----
19 |
20 | func Retryable(e error) error {
21 | return &RetryableError{Err: e}
22 | }
23 |
24 | func IsRetryable(e error) bool {
25 | return errors.As(e, &retryableErr)
26 | }
27 |
28 | type MaxRetryReached struct {
29 | TriedTimes int
30 | Err error
31 | }
32 |
33 | var maxRetryReachedErr *MaxRetryReached
34 |
35 | func (e *MaxRetryReached) Error() string {
36 | return fmt.Sprintf(`exceeded retry limit: %d times, error: %s`, e.TriedTimes, e.Err.Error())
37 | }
38 |
39 | func ReachedMaxRetry(e error) bool {
40 | return errors.As(e, &maxRetryReachedErr)
41 | }
42 |
43 | type Func func(attempt int) (err error)
44 |
45 | /*
46 | usage:
47 |
48 | e :=retry.Do(10, func(attempt int ) error {
49 | if e == network_error {
50 | return Retryable(e)
51 | }
52 | return e
53 | })
54 | */
55 | func Retry(maxAttempt int, fn Func) error {
56 | attempt := 0
57 | var e error
58 |
59 | for {
60 | e = fn(attempt)
61 | if e == nil || !IsRetryable(e) {
62 | break
63 | }
64 | attempt++
65 | if attempt >= maxAttempt {
66 | return &MaxRetryReached{
67 | TriedTimes: maxAttempt,
68 | Err: e,
69 | }
70 | }
71 | }
72 | return e
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/pdu/InvalidHeaderValueException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 Esmertec AG.
3 | * Copyright (C) 2007 The Android Open Source Project
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package spam.blocker.util.pdu;
19 |
20 |
21 | /**
22 | * Thrown when an invalid header value was set.
23 | */
24 | public class InvalidHeaderValueException extends MmsException {
25 | private static final long serialVersionUID = -2053384496042052262L;
26 |
27 | /**
28 | * Constructs an InvalidHeaderValueException with no detailed message.
29 | */
30 | public InvalidHeaderValueException() {
31 | super();
32 | }
33 |
34 | /**
35 | * Constructs an InvalidHeaderValueException with the specified detailed message.
36 | *
37 | * @param message the detailed message.
38 | */
39 | public InvalidHeaderValueException(String message) {
40 | super(message);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/history/HistoryScreen.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.history
2 |
3 | import androidx.compose.foundation.layout.Column
4 | import androidx.compose.foundation.lazy.rememberLazyListState
5 | import androidx.compose.runtime.Composable
6 | import androidx.compose.runtime.derivedStateOf
7 | import androidx.compose.runtime.getValue
8 | import androidx.compose.runtime.remember
9 | import androidx.compose.ui.platform.LocalContext
10 | import spam.blocker.ui.widgets.FabWrapper
11 |
12 |
13 | @Composable
14 | fun HistoryScreen(
15 | vm: HistoryViewModel,
16 | ) {
17 | val ctx = LocalContext.current
18 |
19 | // Hide FAB on scrolling to the last item
20 | val listState = rememberLazyListState()
21 | val fabVisible by remember {
22 | derivedStateOf {
23 | val lastVisibleIndex = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: -1
24 | val lastItemIndex = listState.layoutInfo.totalItemsCount - 1
25 | lastVisibleIndex < lastItemIndex || listState.firstVisibleItemIndex == 0
26 | }
27 | }
28 |
29 | FabWrapper(
30 | fabRow = { positionModifier ->
31 | // Two FABs
32 | HistoryFabs(
33 | visible = fabVisible,
34 | vm = vm,
35 | modifier = positionModifier,
36 | )
37 | }
38 | ) {
39 | Column {
40 | HistoryList(
41 | lazyState = listState,
42 | vm = vm,
43 | )
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notification.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
18 |
19 |
24 |
25 |
31 |
32 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_open_msg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/pdu/MmsException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 Esmertec AG.
3 | * Copyright (C) 2007 The Android Open Source Project
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package spam.blocker.util.pdu;
19 |
20 | /**
21 | * A generic exception that is thrown by the Mms client.
22 | */
23 | public class MmsException extends Exception {
24 | private static final long serialVersionUID = -7323249827281485390L;
25 |
26 | /**
27 | * Creates a new MmsException.
28 | */
29 | public MmsException() {
30 | super();
31 | }
32 |
33 | /**
34 | * Creates a new MmsException with the specified detail message.
35 | *
36 | * @param message the detail message.
37 | */
38 | public MmsException(String message) {
39 | super(message);
40 | }
41 |
42 | /**
43 | * Creates a new MmsException with the specified cause.
44 | *
45 | * @param cause the cause.
46 | */
47 | public MmsException(Throwable cause) {
48 | super(cause);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_post.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
20 |
28 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.ui.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple80 = Color(0xFFD0BCFF)
6 | val PurpleGrey80 = Color(0xFFCCC2DC)
7 | val Pink80 = Color(0xFFEFB8C8)
8 |
9 | val Purple40 = Color(0xFF6650a4)
10 | val PurpleGrey40 = Color(0xFF625b71)
11 | val Pink40 = Color(0xFF7D5260)
12 |
13 | val Purple200 = Color(0xFFBB86FC)
14 | val Purple500 = Color(0xFF6200EE)
15 | val Purple700 = Color(0xFF3700B3)
16 | val Teal200 = Color(0xFF03DAC5)
17 | val Teal700 = Color(0xFF018786)
18 | val Black = Color(0xff000000)
19 | val White = Color(0xffFFFFFF)
20 | val Grey = Color(0xffE4E4E4)
21 | val SwissCoffee = Color(0xffD1C8C8)
22 | val DarkGrey = Color(0xff404040)
23 | val MidGrey = Color(0xffb0b0b0)
24 | val ColdGrey = Color(0xffa0a0a0)
25 | val SilverGrey = Color(0xffC0C0C0)
26 | val DimGrey = Color(0xff696969)
27 | val LightGrey = Color(0xffcccccc)
28 | val Grey424242 = Color(0xff424242)
29 | val Grey383838 = Color(0xff383838)
30 | val Salmon = Color(0xfffa8072)
31 | val YellowGreen = Color(0xff9ACD32)
32 | val LightGreen = Color(0xff90cE90)
33 | val Emerald = Color(0xff50c878)
34 | val Orange = Color(0xffffa500)
35 | val OrangeRed = Color(0xffff4500)
36 | val DarkOrange = Color(0xffff8c00)
37 | val DodgeBlue = Color(0xff1E90FF)
38 | val SkyBlue = Color(0xff00BFFF)
39 | val MayaBlue = Color(0xff6ed0ff)
40 | val GhostWhite = Color(0xfffafaff)
41 | val EerieBlack = Color(0xff1d1d1d)
42 | val Black111111 = Color(0xff111111)
43 | val Black2d2d2d = Color(0xff2d2d2d)
44 | val RaisinBlack = Color(0xff201f25)
45 | val LightMagenta = Color(0xffea86ff)
46 | val Priority = LightMagenta
47 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_replace.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/spam/blocker/util/Xml.kt:
--------------------------------------------------------------------------------
1 | package spam.blocker.util
2 |
3 | import org.w3c.dom.Document
4 | import org.w3c.dom.NodeList
5 | import java.io.ByteArrayInputStream
6 | import javax.xml.parsers.DocumentBuilderFactory
7 | import javax.xml.xpath.XPathConstants
8 | import javax.xml.xpath.XPathFactory
9 |
10 |
11 | object Xml {
12 | fun parseString(
13 | bytes: ByteArray,
14 | xpathStr: String,
15 | ): String {
16 | val document = parseXml(bytes)
17 | val xPath = XPathFactory.newInstance().newXPath()
18 |
19 | return xPath.evaluate(xpathStr, document, XPathConstants.STRING) as String
20 | }
21 | fun parseRules(
22 | bytes: ByteArray,
23 | xpathStr: String,
24 | ): List