Blokada

This application blocks ads and trackers, doesn't require root and works for all the apps on your Android phone. Check out how it works here.

Open Source

Blokada Source Code

Author

blokadaorg

Description

The official repo for Blokada apps.

#adblocker#adblocking#android#blocker#blokada#dns#ios#privacy#security#vpn

Homepage

https://blokada.org

Repository

  • LicenseMPL-2.0
  • Created19 Nov 16
  • Primary languageDart
  • Size171,497 KB
  • Stars3,268
  • Forks230
  • Watchers3,268

Language Usage

Language Usage

Project Health

  • Last commit6 days ago
  • Open issues207
  • Latest releaselanding.796c

Top Contributors

Recent Commits

  • blokada-ci[bot](24 Oct 26)

    sync: update translate strings to: 00d38 (#1391) Co-authored-by: blokada-ci[bot] <276300274+blokada-ci[bot]@users.noreply.github.com>

  • Karol Gusak(23 Oct 26)

    feat(stats): Pulse motion, a logging-off preview and an insight line (#1388) * feat(stats): draw the Pulse trend in, bars on top domains, count up the total The trend line draws in when Pulse opens and when the range changes, once that range's numbers are in, and stays still on the 30 s refresh. Each draw-in rebuilds the chart under a new key and animates only while it runs. The chart's data points now compare by value, so a rebuild with the same data no longer counts as new data. Each Top domains row gets a thin bar in the tab's colour, sized against the top entry, growing in when the list appears or the range changes. The all-time total counts up like the other numbers, keeping the 12.3K form. With Reduce Motion: no draw-in, bars at their width, no count-up (the blocked and allowed counters included). Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(stats): preview Pulse and Activity while activity logging is off With logging off (the default), Privacy Pulse and Activity opened a plain settings page. They now show sample data, blurred and marked "Sample", behind one offer: what turning logging on keeps (requests from your devices, for 24 hours, off any time in Settings), one button that turns it on (retention "24h"), and the privacy policy link. Logging stays off until that tap; the Settings switch is unchanged. The offer reuses FreemiumScreen, which now takes a badge, its own action and a footer; the sample uses the freemium sample's names, fixed so it looks the same each time. Pulse draws it through its usual sections from a SampleStatsController. The sample is hidden from screen readers and automation; the offer and button are not (new id: logging_enable). After the tap, empty lists say "Collecting your first results" instead of "Nothing to show yet" until the first results load (this session only). Pins deps/translate to the branch with the new strings and regenerates en.json. BlurBackground no longer sets state after it is gone. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(stats): one insight line at the top of Privacy Pulse The Pulse card repeated the screen title next to its icon, then a generic sentence. It now leads with one line from the numbers already loaded: "36 blocked in 24 h · 12% fewer than the 24 h before", or "... the week before" on 7 d. The comparison is the CounterDelta the chart loads; without one (or at 0%) the line shows the count only. Counts only, with singular and plural forms, big counts in the short 12.3K form, and a placeholder bar until the numbers load. The 24 h / 7 d switch stays in the card, with the line on its own row under it so it doesn't wrap. Pins deps/translate to the commit with the new strings and regenerates en.json. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): start the trend line draw-in once the chart's data is ready Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(golden): Privacy Pulse with the insight line and toplist bars Co-Authored-By: Claude Opus 5.5 <[email protected]> * sync: pin translate to master with the new strings Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(23 Oct 26)

    feat(stats): denser Activity rows grouped by time (#1387) * sync: pin translate to the activity time group strings Points deps/translate at blokadaorg/translate branch claude/activity-time-groups (85cafb347) and regenerates en.json. Move the pin to master once that merges. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(stats): denser Activity rows grouped by time Each Activity row led with a 52 px saturated red or green shield, so the log looked alarming and only about seven rows fit on a screen. Rows now lead with the domain, with a 24 px shield (cross or check kept inside, so colour is never the only signal) before the chevron, and a repeat count shares the time line. Rows are 56 px, and the loading placeholder matches. The list is split under "Just now" (last hour), "Earlier today", "Yesterday", and the date for older days. Groups are worked out on every build, so pages loaded later and refreshes regroup; a new group from a refresh fades in like its rows. Headers are marked as headers for screen readers, and a row reads domain, blocked or allowed, then time. Shared with Family's device activity screen, which gets the same change. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): keep Activity rows to one line per text, at the placeholder height Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(golden): Activity with grouped, denser rows Co-Authored-By: Claude Opus 5.5 <[email protected]> * sync: pin translate to master with the new strings Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Johnny Bergström(23 Oct 26)

    feat(ui): iOS 26 bar buttons and a bare back chevron on iOS (#1378) * feat(ui): iOS 26 bar buttons and a bare back chevron on iOS On iOS the top bars now draw bar actions (Search, Add, Save, Done, Cancel, End) in superellipse bubbles and the back button as a chevron alone in a round bubble, as iOS 26 does. The previous screen's name moves from the screen into the back button's semantics value, so VoiceOver still says where back goes; the navBack automation id stays. Android keeps the current bars until its own look is decided. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_014aA2iLP8qyuhejxUjBAm2C * fix(ui): 44pt bar bubbles that show on card-coloured bars Make the iOS bubbles Apple's 44pt minimum tap target and tint them from the text colour so they show on page- and card-coloured bars alike. Centre short labels in the bubble, share the back-chevron fade between both branches and read the platform once per build. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_014aA2iLP8qyuhejxUjBAm2C * docs(family): say where the rule editor's device name shows on each platform Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NBJKfuruGv4ToB4QBFqDgn --------- Co-authored-by: Claude <[email protected]>

  • Johnny Bergström(23 Oct 26)

    Send the user agent and client tools with every support chat message (#1377) Messages in an open chat now carry the user agent and client tools, as the session start already does, so the server sees the current app version after an update mid-chat. The real user agent goes into the JSON, not the Http placeholder, so it is escaped and the user's own message text is never rewritten. Claude-Session: https://claude.ai/code/session_014aA2iLP8qyuhejxUjBAm2C Co-authored-by: Claude <[email protected]>

  • blokada-ci[bot](23 Oct 26)

    sync: update translate strings to: d5dac (#1386) Co-authored-by: blokada-ci[bot] <276300274+blokada-ci[bot]@users.noreply.github.com>

  • Karol Gusak(22 Oct 26)

    feat(stats): smooth content changes in pulse and activity (#1385) * feat(stats): loading placeholders instead of spinners One shared LoadingPlaceholder: grey rows shaped like the content with a soft shimmer, static with Reduce Motion. Used on the Home counter, Top domains, Recent activity, and the Activity list and its load-more, so nothing jumps when data arrives. "Waiting for data" now shows only for a list that loaded empty, and a failed Activity load shows the error with a retry instead of waiting forever. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): size the counter placeholder by one line of the number A fixed 40px box moved the power button on the inactive Home screen, where the counter card is laid out but hidden. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): a failed page waits for the retry tap; no paging before the first load Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(stats): smooth content changes in pulse and activity Closing the weekly card shrinks and fades it out before it is removed, so the content below slides up. Blocked/Allowed and 24h/7d crossfade the lists in 150 ms, with the card height following. Activity pull to refresh now reloads in place: the rows stay while the indicator spins, rows new since the last load fade in, a failure still shows the error, and a light haptic marks the start. With Reduce Motion these are plain fades with no size animation. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): no page loads while a pull to refresh is in flight The refresh keeps the rows (and _isReady) on screen, so the paging guard from the base no longer covered it: a page could start from the old cursor and mix with the fresh first page. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): the Activity list is not ready until a pull to refresh is done Clearing the list sent a change that marked it ready during the reload, so a page could load and mix with the fresh first page. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(22 Oct 26)

    feat(stats): loading placeholders instead of spinners (#1384) * feat(stats): loading placeholders instead of spinners One shared LoadingPlaceholder: grey rows shaped like the content with a soft shimmer, static with Reduce Motion. Used on the Home counter, Top domains, Recent activity, and the Activity list and its load-more, so nothing jumps when data arrives. "Waiting for data" now shows only for a list that loaded empty, and a failed Activity load shows the error with a retry instead of waiting forever. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): size the counter placeholder by one line of the number A fixed 40px box moved the power button on the inactive Home screen, where the counter card is laid out but hidden. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): a failed page waits for the retry tap; no paging before the first load Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): the Activity list is not ready until a pull to refresh is done Clearing the list sent a change that marked it ready during the reload, so a page could load and mix with the fresh first page. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(22 Oct 26)

    fix(log): keep the error on errors logged outside a trace (#1379) * fix(log): keep the error on errors logged outside a trace LogTracerActor.sink dropped err and stack when no trace was open for the marker, so callers like the Adapty purchase-failure handler logged only their message. The share log said "Failed purchase" with no error code. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(log): check the stack trace survives the untraced path too Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(22 Oct 26)

    feat(ui): one press feedback, and haptics on segments and the Plus location (#1381) * feat(home): draw the protection ring round and pulse when confirmed The ring draws clockwise from the top over 600 ms when protection comes on and unwinds when it goes off, instead of fading. Once protection the user switched on is confirmed, the ring pulses outward once with the success haptic; opening Home with protection already on does not pulse. Adds Motion.reduced, the app's one Reduce Motion check. With it on, the rings fade as before and only the haptic plays. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(ui): one press feedback for cards, buttons and rows Touch (cards and buttons) shrinks to 97% with its highlight, easing in over 100 ms and out over 200 ms; with Reduce Motion it only highlights. The power button opts out of the shrink. CommonClickable rows ease the same highlight in and out instead of snapping, and the weekly report card uses CommonClickable instead of a Material InkWell ripple. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(home): haptics on the power button tap and while the ring winds A power button tap gives a medium thump. After a tap, the ring gives a selection tick at each quarter as it draws or unwinds; opening Home or a reconnect stays silent. Choosing a pause gives a light impact. Success is now a rising light, medium, heavy run with the pulse. With Reduce Motion, no ticks. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(ui): haptics on segmented controls and the Plus location Segmented controls (24h/7d, Blocked/Allowed, the activity and exceptions tabs, the domain dialog) go through BlokadaSegmentedControl, which gives a selection click when the user picks another segment, as BlokadaSwitch does for switches. Tapping the Plus location bar gives a medium tap, and a light impact confirms once a newly picked location is up. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(ui): rising and falling haptics for switching on and off Switching on (power button, Plus switch) plays a rising medium-heavy double; switching off or picking a pause plays a falling heavy-light double. Plus plays the success run once it is connected, from the switch or a newly picked location, matching protection. BlokadaSwitch takes haptic: false so the Plus switch plays its own pattern instead of the selection click. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(ui): play the Plus success haptic only once Plus is up switchPlus returns normally for a start the OS still holds (#1382), so check the app status before the success run. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(ui): play the Plus success haptic when Plus comes up, even later A start the OS holds comes up minutes after switchPlus returns. The Plus bar now remembers the user's switch-on and plays the success run when the app status reaches activatedPlus; switching off or a failed start clears it. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(ui): honour iOS Reduce Motion and skip a late pulse under it Flutter reports iOS Reduce Motion as accessibilityFeatures.reduceMotion, separate from disableAnimations, so Motion.reduced now reads both. A pulse queued while the ring drew no longer plays if Reduce Motion came on meanwhile; the success haptic still does. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(home): check for no pulse inside the pulse window under Reduce Motion Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): hide a running pulse once Reduce Motion is on Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): disarm ring ticks once the ring has moved, not only once it ticked A reverse that settles without crossing a quarter left the ticks armed, so a later switch-on could tick without a tap. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(22 Oct 26)

    feat(home): draw the protection ring round and pulse when confirmed (#1380) * feat(home): draw the protection ring round and pulse when confirmed The ring draws clockwise from the top over 600 ms when protection comes on and unwinds when it goes off, instead of fading. Once protection the user switched on is confirmed, the ring pulses outward once with the success haptic; opening Home with protection already on does not pulse. Adds Motion.reduced, the app's one Reduce Motion check. With it on, the rings fade as before and only the haptic plays. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(home): haptics on the power button tap and while the ring winds A power button tap gives a medium thump. After a tap, the ring gives a selection tick at each quarter as it draws or unwinds; opening Home or a reconnect stays silent. Choosing a pause gives a light impact. Success is now a rising light, medium, heavy run with the pulse. With Reduce Motion, no ticks. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(ui): honour iOS Reduce Motion and skip a late pulse under it Flutter reports iOS Reduce Motion as accessibilityFeatures.reduceMotion, separate from disableAnimations, so Motion.reduced now reads both. A pulse queued while the ring drew no longer plays if Reduce Motion came on meanwhile; the success haptic still does. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(home): check for no pulse inside the pulse window under Reduce Motion Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): hide a running pulse once Reduce Motion is on Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): disarm ring ticks once the ring has moved, not only once it ticked A reverse that settles without crossing a quarter left the ticks armed, so a later switch-on could tick without a tap. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(22 Oct 26)

    fix(plus): keep Plus on while iOS holds the VPN start after an update (#1382) * fix(plus): keep Plus on while iOS holds the VPN start after an update Updating the app while Plus is connected puts iOS's VPN session into an "Updating" state that holds every start until the new extension is registered: 25s to the full 300s limit, measured on device. The app gave up after 3.5s, then deleted the lease, turned Plus off and showed the VPN error. iOS now reports a held start as vpnStartPending after three 10s waits, and the app treats it as pending, not failed: Plus and the lease stay, the app shows Cloud, and iOS starts the tunnel itself through on-demand once the update ends. The status reaction no longer requeues a pending start, and turning off cancels a held start, including one still in flight, by switching on-demand off. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(plus): leave a held VPN start alone on every recovery path Review findings: a retry's start coming back held still tore Plus down, the foreground recovery and the status reaction both re-requested a held start (cancelling and requeuing it), and setActualStatus started again on an off report while the OS held one. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(plus): expire a held VPN start after six minutes A hold that ends without the tunnel coming up sends no signal, so the pending state now lapses just above iOS's 300s limit and the usual recovery resumes. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • blokada-ci[bot](22 Oct 26)

    sync: update translate strings to: 24fcb (#1383) Co-authored-by: blokada-ci[bot] <276300274+blokada-ci[bot]@users.noreply.github.com>

  • Karol Gusak(21 Oct 26)

    feat(settings): Your plan section with renewal status, manage and restore (#1367) * sync: pin translate to the Your plan and pause scope strings Points deps/translate at blokadaorg/translate#502 and regenerates en.json. Move the pin to master once that PR merges. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(settings): Your plan section with renewal status, manage and restore Settings gets a "Your plan" section (blokadaorg/issue-tracker#454): a plain status ("Blokada Cloud · renews 14 Feb" / "ends" / "active until" / expired) with a locale-formatted date, Cloud to Plus through the existing upgrade placement, Manage subscription routed by where the plan was bought, and Restore purchases next to Restore Account ID. Renews vs ends comes from the active Adapty access level (willRenew, expiresAt, store), read through two new PaymentChannel calls: Flutter Adapty on iOS and Family, a new pigeon call into the native SDK on Android six. Without a store level (web, ticket, store unreachable) it falls back to the account's end date. The store comes from the access level, then the backend payment source, so a plan bought in the other platform's store opens that store's page; web plans open the dashboard. Restore reuses the paywall's path: an active level checks out as a restore, none shows the restore-not-found message, a store error the restore-failed sheet. Purchase and paywall flows are unchanged. Also moves the hardcoded English strings the issue lists to Crowdin keys. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(golden): update settings goldens for the Your plan section Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(settings): keep Your plan to this account and out of URLs Review fixes for blokadaorg/issue-tracker#454: - Restore purchases only shows without an active plan, like the paywall, and PlanActor refuses it for an active account: checkout replaces the account with whichever one owns the store purchase. - Web plans no longer open app.blokada.org/account?account-id=…, which put the account's credential in a URL. Manage now signs in through the one-time attach link (AttachActor.openInBrowser); it lands on the dashboard home, as that link can't target a page. Only offered while active (the backend mints links for active accounts only) and not for Family. Drops LinkId.manageSubscriptionsWeb. - Only an Adapty level of the account's own tier and of this account's Adapty customer (customerUserId, new on both the Flutter and the native path) describes the plan; anything else falls back to the end date with the store from the payment source. - Settings restore failures always show (reportAlways), even after an earlier paywall error; paywall behaviour is unchanged. - A failed Manage tap shows an error instead of nothing. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(golden): settings without Restore Purchases for an active plan Co-Authored-By: Claude Opus 5.5 <[email protected]> * chore(translate): pin the merged strings on master Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(21 Oct 26)

    feat(home): say that pause is account-wide, show pauses from other devices (#1368) * sync: pin translate to the Your plan and pause scope strings Points deps/translate at blokadaorg/translate#502 and regenerates en.json. Move the pin to master once that PR merges. Co-Authored-By: Claude Opus 5.5 <[email protected]> * feat(home): say that pause is account-wide, show pauses from other devices v6 pause is one flag per account on /v2/device, so pausing one phone pauses every device on the account and the others look switched off by themselves (blokadaorg/issue-tracker#455, #39, #154). The pause sheet now says "Pauses ad blocking on all devices using this account". Each install remembers whether it issued the current pause (PauseIssuedHereValue, written where DeviceStore puts the pause flag); a paused, active account whose pause this install did not issue shows "Paused from another device · Resume" under the power button instead of "Tap to activate". Tapping it resumes as before. The origin starts unknown and is only learned once the install pauses or sees the account unpaused, so an app updated during its own pause never blames another device. No backend change; the power button is untouched. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): keep the pause origin current and the device refresh safe Review fixes for blokadaorg/issue-tracker#455: - NullableAsyncValue.fetch no longer publishes a value it loaded if the value changed during the load; it keeps and returns the newer one. Home's initial origin read could otherwise overwrite a pause issued meanwhile. - A failed pause-origin write is logged instead of aborting the device refresh, or skipping the refresh after a pause the server already took. - The paused-from-another-device text has the button role, since tapping it resumes; the test now taps it and checks resume runs. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(core): let concurrent fetches await the in-flight load A fetch that joined a load in progress waited for the next change event. Since a stale load no longer publishes, a change landing before that second fetch left it waiting forever. Concurrent fetches now await the shared load future, which resolves to the current value either way; a failed load also no longer wedges later fetches. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): handle the pause-origin startup race in HomeActions Reverts the shared NullableAsyncValue change (core is identical to main again) and drops its tests. HomeActions now reads the stored origin without publishing it and only applies it when no change arrived during the read, so a late stored value never undoes a newer pause. Co-Authored-By: Claude Opus 5.5 <[email protected]> * chore(translate): pin the merged strings on master Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(21 Oct 26)

    refactor(stats): one stats controller for Home and Privacy Pulse (#1369) * refactor(stats): one stats controller for Home and Privacy Pulse Privacy Pulse started its own fetches from eight places and kept the results in widget state, and the Home counter ran its own refresh timer. A failed fetch had no error state, and Home and Pulse could show different 24h numbers. - StatsController (Actor + Values): owns fetching, refresh and the selected range. It exposes stats, counters, toplists and recent sections, each loading/ready/empty/error. Screens only draw them. - Home's 30 s refresh moves into it. The counter keeps its gating rules (protection on, foreground, not covered) and reports them. - Pulse's 24h numbers are Home's stats, not a separate fetch. - computeStatsBaselines buckets points by their hour, so the 24h histogram covers the same hours as the 24h counters. - Failed fetches show an error with a retry. fetchToplists throws instead of blanking the toplist, and toplistsLoading leaves MobX. - UiStats moves to platform/stats/model.dart. Family re-exports it. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(golden): Home's 24h count matches Pulse after the bucketing fix Home shows 36 blocked (was 38, a 25-hour sum), the same as Privacy Pulse; the 24h sparkline shifts by one hourly bucket. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): keep the last count on a failed refresh; retry failed Pulse stats - Home counter: a failed refresh keeps the last count and the tap still opens Privacy Pulse; the retry shows only when there is nothing to show. - Pulse charts: stats that failed with nothing loaded show the error with a retry instead of zeros; a counters failure still comes first. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(stats): drop loads that finish after the device was renamed A stats, weekly counters, delta, toplist or recent activity load that started under the old device name no longer publishes once the name changed; the rename starts a new load. StatsStore's shared endpoint cache is unchanged (a pre-existing, store-level race). Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(21 Oct 26)

    refactor(home): power button state and a protection confirmed event (#1366) * refactor(home): derive power button state and a protection confirmed event The power button kept its rules inline and signalled "protection is on" through a HomeStore flag set when its own spinner stopped, which also fired on app start and every reconnect. - powerButtonState(): pure mapping from status, freemium and pause time to what the button shows and what a tap does. - PowerActor: runs the tap actions and emits onProtectionConfirmed once per user switch-on (also after DNS onboarding, within 5 minutes). - HomeStore removed; the button sequences its stats rings locally. - Both button reactions are disposed; home_section's unused controllers and undisposed autorun are gone, as are the never-drawn ic_power and ic_pause images. Co-Authored-By: Claude Opus 5.5 <[email protected]> * test(home): drop redundant mockito import Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(home): drop the pending activation when the toggle fails A failed toggle left the request pending, so protection coming up later another way within five minutes counted as confirmed for that tap. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • dependabot[bot](20 Oct 26)

    build(deps): bump follow-redirects (#1376) Bumps the appium-wdio-npm-security group with 1 update in the /automation/appium/wdio directory: [follow-redirects](https://github.com/follow-redirects/follow-redirects). Updates `follow-redirects` from 1.16.0 to 1.16.1 - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.16.0...v1.16.1) --- updated-dependencies: - dependency-name: follow-redirects dependency-version: 1.16.1 dependency-type: indirect dependency-group: appium-wdio-npm-security ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

  • Karol Gusak(20 Oct 26)

    fix(appium): confirm the support chat sent a command before moving on (#1375) The CI iPhone updated to iOS 27 overnight on Oct 20, and since then every `cc restore` the smoke suite typed into the support chat was silently dropped, so the phone stayed on whatever account it already had. The paywall spec, which needs the inactive account, was the only one to notice. On iOS 27 the app takes in text typed through XCTest a moment late. A send tapped about 0.3s after typing, as the harness did, does nothing and the field keeps the text; a second later the same tap sends. The `~Send` selector also now resolves to the keyboard's return key, whose tap blocked for 7.5s and was dropped the same way. - tap the composer's own send button (far right of the input row) instead of matching "Send" by label - after the tap, wait for the composer to give up the text and tap again until it does, for up to 15s - fail with a clear error if the command never leaves the composer, instead of relaunching and letting a later spec report the wrong account Reproduced and checked on the CI iPhone (iOS 27.0.1) with the Appium explorer. Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(20 Oct 26)

    ci(glm-review): name runs after the PR and raise the diff limit to 128k (#1374) A comment-triggered run carries no PR number, so the run name now starts with "GLM review: #<pr>" for the reviewer watcher to find this PR's run. PR-Agent also capped what it sent at its 32k default, which cuts large diffs; max_model_tokens is now 128k. Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(20 Oct 26)

    chore(coderabbit): stop the review status comment on every PR (#1373) With automatic reviews off, CodeRabbit posted a "Review skipped" comment on every new PR. Reviews still run on `@coderabbitai review`. Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(20 Oct 26)

    ci: GLM PR review on request via PR-Agent (#1372) * ci: GLM PR review on request via PR-Agent GLM is one of the PR reviewers an agent rotates through when another hits its limit. A team member comments `/review` (or `/improve`) and PR-Agent reviews the PR with GLM 5.3 through Z.ai's pay-as-you-go API, posting each finding as a line comment. Outside commenters cannot trigger it, and a review sends at most 200k tokens. Co-Authored-By: Claude Opus 5.5 <[email protected]> * ci(glm-review): label the review comment as GLM PR-Agent's summary comment does not say which model reviewed the PR. A step after it appends "Reviewed by GLM 5.3 (Z.ai) via PR-Agent", again after each round since PR-Agent rewrites the comment. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(20 Oct 26)

    chore: remove the Gemini Code Assist config (#1371) Google shut down the free Gemini Code Assist GitHub app in July 2026, so it no longer reviews PRs here and its config has nothing to configure. Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(20 Oct 26)

    chore: configure CodeRabbit and Gemini Code Assist to review on request (#1370) Both bots are PR reviewers an agent rotates through when another hits its limit, so neither reviews on its own: CodeRabbit runs on `@coderabbitai review`, Gemini on `/gemini review`. CodeRabbit approves once its comments are resolved. Both skip generated files: Adapty fallback exports, translations, lockfiles and Pigeon output. Co-authored-by: Claude Opus 5.5 <[email protected]>

  • blokada-ci[bot](20 Oct 26)

    sync: update translate strings to: b9c52 (#1365) Co-authored-by: blokada-ci[bot] <276300274+blokada-ci[bot]@users.noreply.github.com>

  • Johnny Bergström(19 Oct 26)

    fix(ui): drop the link underline from bar actions (#1364) The contrast pass gave every text link a near-black color and an accent underline on light backgrounds. In a bar the underline is a second affordance nobody needs: a back label already follows a chevron and an action already sits in the trailing corner, so it read as a stray rule under the nav bar rather than as a link. - linkStyle takes `underline: false`; the near-black link color, which is what actually fixed the 1.97:1 contrast, is unchanged everywhere - applied to the two top_bar back labels, the BackTitleNavBar back label, and the Search / Add trailing actions, so this spans v6 and Family - body links (retention policy, Show all) keep the underline: those have no other affordance Verified on the iOS 27 simulator in light mode. Re-renders the four light goldens that draw a bar link (activity, advanced, privacy_pulse, settings); dark goldens are unchanged because dark mode leaves linkUnderline null. Ref: blokadaorg/issue-tracker#473 Co-Authored-By: Claude Opus 5 <[email protected]>

  • Johnny Bergström(19 Oct 26)

    build(deps): stop cloning landing-github-pages nested submodules (#1363) The app reads only landing-github-pages itself (the Safari extension's oisd-small symlink). Its nested tracker-radar and translate submodules are build inputs of that repo's mirror sync, so recursive init cloned a large DuckDuckGo repo into every fresh worktree and CI job for nothing. - docs and dep-validate skill: git submodule update --init - workflows: submodules: true instead of recursive - validation: fresh worktree init ~85 s, gen-rules resolves the oisd symlink, make test passes Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Johnny Bergström(19 Oct 26)

    fix(http): wait 30s for requests before timing out (#1361) Some API calls do slow work on the server before they answer and can take over 15s. The iOS client gave up at 15s (Android at 10s), and the HTTP layer then retried a request the server had already handled, which could fail with a 400 and lose the original answer. - raise the native HTTP timeout to 30s on iOS and the read timeout to 30s on Android; connect timeout stays 5s - keep the VPN stop wait in WgService at 15s via its own constant Retries still use 3 attempts, so a hung request now takes up to ~90s to fail instead of ~45s on iOS. Not retrying POSTs after a timeout needs the native layers to report timeouts distinctly and is left for later. Validation: Dart unchanged; Swift sources parse; make test passed on the earlier revision of this branch (581). Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Johnny Bergström(19 Oct 26)

    build(ios): rebuild a stale Flutter module before device runs (#1362) make -C ios run-six linked whatever was already in common/build/ios-spm, so a device build after pulling new Dart code silently shipped the old Flutter module. run-six, run-family and the appium-install targets now hash the path and sub-second mtime of every non-ignored file in common/ (tracked and untracked, outside test/ and docs/) and rebuild when it differs from the hash stamped after the last successful build-ios. Hashing the whole tree instead of a list of inputs means a missed input costs an extra rebuild, never a stale one; generated and build output stays out via .gitignore. The stamp records the hash taken before the build, so an edit made during it forces another rebuild. The mocked simulator targets drop the stamp before they overwrite the Debug module, so the next device run rebuilds the real one. Both outcomes are printed. The stamp is written with && since Xcode's GNU Make 3.81 ignores .SHELLFLAGS, so -e does not stop a recipe after a failed build. Validation (inner build stubbed, under sh, dash and zsh): no stamp, an edited generator script, a deleted asset, a new untracked file, an edited vendor file and an edit within the same second each rebuild; an unchanged tree, a test edit and a regenerated file report up to date; an edit during the build is caught on the next run; a failed build fails the target and stays stale; the check takes 0.03s. Co-authored-by: Claude Opus 5.5 <[email protected]>

  • Karol Gusak(19 Oct 26)

    fix(home): own screen reader label and translated state for the power button (#1355) * fix(home): own screen reader label and translated state for the power button The power button borrowed the Settings 'Protection' header as its label, and screen readers read its state as the untranslated 'active'/'inactive' value the Appium flows depend on. It now has its own label and a translated on/off hint; the value is unchanged for Appium. Strings from translate#497; re-pin deps/translate to master once it merges. Co-Authored-By: Claude Opus 5.5 <[email protected]> * chore(translate): pin the merged power button strings on master Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>

Blokada Security

2.4/10

Repo Security Summary

Updated 24 Aug 26

  • Maintained10/10
  • Code-Review0/10
  • Dangerous-Workflow0/10
  • PackagingN/A
  • CII-Best-Practices0/10
  • Token-Permissions0/10
  • Security-Policy0/10
  • Binary-Artifacts9/10
  • Fuzzing0/10
  • Pinned-Dependencies1/10
  • Signed-Releases0/10
  • License10/10
  • Branch-Protection3/10
  • SAST0/10

Blokada Website

Website

Blokada - the popular mobile adblocker and VPN for Android and iOS

Keep all your devices protected with Blokada content filtering and encryption.

Redirects

Does not redirect

Security Checks

All 65 security checks passed

Server Details

  • IP Address104.21.26.94
  • LocationSan Francisco,California,United States of America,NA
  • ISPCloudFlare Inc.
  • ASNAS13335

Associated Countries

  • USUS
  • CACA

Safety Score

Website marked as safe

100%

Trackers

No known trackers found

Blacklist Check

blokada.org was found on 0 blacklists

  • AntiSocial Blacklist
  • Artists Against 419
  • Badbitcoin
  • Bambenek Consulting
  • CERT Polska
  • CoinBlockerLists
  • CRDF
  • CryptoScamDB
  • EtherAddressLookup
  • EtherScamDB
  • Fake Website Buster
  • MetaMask EthPhishing
  • NABP Not Recommended Sites
  • OpenPhish
  • PetScams
  • PhishFeed
  • PhishFort
  • Phishing.Database
  • PhishStats
  • PhishTank
  • Phishunt
  • RPiList Not Serious
  • Scam.Directory
  • SecureReload Phishing List
  • Spam404
  • StopGunScams
  • Suspicious Hosting IP
  • ThreatFox
  • ThreatLog
  • TweetFeed
  • URLhaus
  • ViriBack C2 Tracker

Website Preview

Website preview

Blokada Android App

APK Info

Trackers

No trackers found

    Permissions

    • Access Coarse Location
    • Access Network State
    • Access Wifi State
    • Foreground Service
    • Get Tasks
    • Interact Across Users
    • Internet
    • Post Notifications
    • Read Logs
    • Read Phone State
    • Receive Boot Completed
    • Request Delete Packages
    • Use Biometric
    • Use Fingerprint
    • Vibrate
    • Wake Lock
    • Write External Storage
    • Set Alarm
    • Billing
    • Dynamic Receiver Not Exported Permission

    Blokada iOS App

    App Info

    Ad Blocker VPN & DNS – Blokada

    This is the official app on App Store from the Blokada open source project. Blokada for iOS uses DNS (Domain Name System) to enable you to have an ad free experience to see only the content you want. Use Blokada Cloud to block ads and trackers, while keeping your DNS traffic confidential. Upgrade to Blokada Plus for encrypting all traffic with our global VPN network. Improve your privacy and secure your Internet against cyber attacks and hackers. ---- Top features: - Supports ad-blocking for every web browser and other app installed. - Blocks sites that distribute malicious content, viruses and fraudulent websites. - DNS based interception for all modern browsers and apps. - Fast and reliable VPN that protects your privacy and encrypts your data. The most compatible ad blocker on the market! • Blocks ads • Saves your data plan • Browse FASTER by loading less data • Increase your battery life What can be blocked? • Block annoying ads: Google AdWords, Google Invite Media, DoubleClick Bid Manager, Liftoff, Bing Ads, Amazon, etc • Block adult websites • Block gambling websites • Block social media trackers: Google Analytics, Facebook Connect, DoubleClick, Google Publisher Tags, Google AdSense, Twitter Button, Yandex.Metrix, Comscore • Block malicious websites: Virus downloads, malicious content, fraudulent websites and manipulated apps ---- Terms of Use: https://go.blokada.org/terms Privacy Policy: https://go.blokada.org/privacy

    Rating

    Rated 3.9 out of 5 stars by 9,478 users

    Version Info

    • Current Version26.8.1020
    • Last Updated28 Aug 26
    • First Released06 Jun 20
    • Minimum iOS Version15.0
    • Device Models Supported127

    App Details

    • IPA Size68.97 Mb
    • PriceFree (USD)
    • Age Advisory4+
    • Supported Languages17
    • DeveloperBlocka AB
    • Bundle IDnet.blocka.app

    Screenshots

    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot
    • App screenshot

    Blokada Reviews

    More Mobile Apps

    About the Data: Blokada

    Change History

    • Amended (androidApp, iosApp)

    Edit Blokada Data

    You can edit Blokada's entry in this section of awesome-privacy.yml by submitting a PR to our GitHub repo.
    Note that some of the information shown above has been aggregated from external sources, a list of these can be found data documentation.

    Origin Data

    Modify Data

    API

    You can access Blokada's data programmatically via our API. Simply make a GET request to:

    https://api.awesome-privacy.xyz/v1/services/blokada

    The REST API is free, no-auth and CORS-enabled. To learn more, view the API Docs or read the API Usage Guide.

    Share Blokada

    Help your friends compare Mobile Apps, and pick privacy-respecting software and services.
    Share Blokada and Awesome Privacy with your network!