qUnleashed is a mobile-first Flutter manager for Flipper Zero, focused on extended Unleashed firmware support, firmware updates, BLE/USB connectivity, remote control, CLI access, and app management. https://git.aperturefox.ru/FlutterAPPs/qUnleashed
  • C 69%
  • Dart 29.7%
  • Kotlin 0.6%
  • C++ 0.3%
  • CMake 0.3%
Find a file
Mykhailo Shevchuk fc1d9e452e
Read the lock state out of the status the firmware actually sends
#79 asked whether desktopIsLocked is a redundant round trip. It is not - a
subscribe never answers with the current state, so a poll is the only way
to learn it - but checking that turned up that the call does not work.

IsLockedRequest answers with an empty frame and puts the state in
command_status: OK for locked, ERROR for unlocked. So hasDesktopStatus()
never matched and the loop under the call was dead, leaving
_lockStatusKnown without a baseline; and on an unlocked device the generic
non-OK handling rejected the call into _start's catch, tripping the
disconnected flag until the next frame cleared it. unlock() had its own
copy, its throw swallowed by a bare catch.

desktopIsLockedNow reads the status back out, as an extension on
FlipperClient in the library's own idiom beside FlipperGpsApi and
FlipperNetworkApi rather than a private method on the one page that needed
it: the trap is as wide as the API, so the next caller reaching for
client.desktop... meets the cooked call instead of rediscovering the
defect. It belongs upstream on FlipperDesktopApi and says so.

Only the bare ERROR means unlocked. Matching on the status rather than the
exception type is deliberate, since FlipperRpcGeneralException is also the
bucket every unmapped status falls into - so firmware without the command
throws instead of reporting a device as unlocked.

The polled answer seeds the baseline without flashing. It is a snapshot
taken before the subscribe landed, so it can be older than a push already
applied, and after a pause it is the first thing seen since - an unlock the
user did on the device by hand was announced as though it had just happened
in the app. unlock() still flashes, which is the point there.

A status rejection no longer flags the whole session disconnected either:
the poll runs last, so the link has answered twice by then, and treating a
command-level rejection as a dropped connection is the same mistake one
status further along. unlock() logs now, since a refused unlock had looked
exactly like a successful one.

Four mutations caught, including the one that showed the first version of
this fix was untested: inverting ERROR to mean locked passed every test it
had. The fake built one exception type for every status and could not
return frames, so it goes through exceptionFromResponse now.

Closes #79, closes #94
2026-09-13 16:54:52 +03:00
.github Keep errors where a shipped build can still be asked for them 2026-09-12 23:33:25 +03:00
.vscode Add VS Code performance launch config 2026-06-16 00:48:59 +03:00
android Say which half of Wrist Remote failed, and stop guessing from the type (#92) 2026-09-13 00:27:24 +03:00
assets Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
fastlane/metadata/android For appstore 2026-05-21 23:54:33 +03:00
ios Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
lib Read the lock state out of the status the firmware actually sends 2026-09-13 16:54:52 +03:00
linux Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
macos Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
screenshots Update screens 2026-06-09 22:01:00 +03:00
test Read the lock state out of the status the firmware actually sends 2026-09-13 16:54:52 +03:00
translations A screen for the log, and a route for what nothing else catches 2026-09-13 11:28:55 +03:00
web Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
windows Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
.gitattributes Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
.gitignore Libs: bump submodules 2026-09-10 12:18:46 +03:00
.gitmodules Перенос репозитория из локального в подмодуль 2026-08-01 18:11:18 +03:00
.metadata flutter files 2026-04-28 15:53:07 +03:00
analysis_options.yaml Bump dartufbt to the atomic SDK and toolchain deploy 2026-09-12 12:53:58 +03:00
CHANGELOG.md Paint: add md5 check animation dir 2026-08-10 18:12:15 +03:00
crowdin.yml Crowdin: map serbian scripts to separate arb files 2026-08-30 21:02:40 +03:00
firebase.json Update app ids 2026-07-04 23:39:32 +03:00
l10n.yaml l10n: add ru localization 2026-08-30 19:03:11 +03:00
LICENSE Add .gitattributes and renormalize line endings (#58) 2026-09-08 14:08:37 +03:00
pubspec.lock Say which half of Wrist Remote failed, and stop guessing from the type (#92) 2026-09-13 00:27:24 +03:00
pubspec.yaml Say which half of Wrist Remote failed, and stop guessing from the type (#92) 2026-09-13 00:27:24 +03:00
README.md Harden the guard against the ways it could pass without looking 2026-09-10 20:04:36 +03:00

qUnleashed

A Flutter companion app for Flipper Zero, built for Unleashed and other firmware.
BLE/USB connection, firmware updates and DFU repair, remote control, archive, file manager and a toolbox — one codebase, five platforms.

Version Flutter Dart Platforms License

qUnleashed is a Flutter companion app for Flipper Zero, written from scratch as an alternative to Flipper Android App and tailored for custom firmware, first of all Unleashed firmware by DarkFlippers. The app is optimized around Unleashed-specific workflows: tracking firmware releases, reading changelogs, downloading updates and installing them directly from the app, while also reworking and extending parts of the original Flipper app experience.

English Telegram Chat Russian Telegram Chat Ukraine Telegram Chat Discord Server

Features

qUnleashed keeps the familiar companion-app workflows from the original Flipper Android App and extends them for custom firmware: USB support on mobile and desktop, firmware repair from DFU mode, phone GPS/internet sharing, a stronger local archive and a bigger toolbox.

Connection

  • BLE and USB on every platform that allows it. qUnleashed connects to Flipper Zero over BLE on all supported platforms, and over a USB serial cable on Android, Windows, macOS and Linux (iOS is BLE-only — Apple does not expose USB serial to apps). Both transports drive the same app surface: device info, archive sync, file manager, apps, remote control and CLI.
  • Multiple devices. The app remembers known Flippers, keeps warm sessions for them, switches between devices instantly and reconnects automatically (a plugged-in USB device takes priority over the last BLE one).
  • Reliable background link. On Android a foreground service keeps the BLE connection alive while the app is in the background.

Firmware

  • Updater. Firmware-centric for Unleashed: release/dev channel tracking with changelogs, downloads and in-app install, including Unleashed variants (base, extra apps, compact). Official firmware channels are supported as well.
  • Repair from DFU mode. If the firmware is broken, qUnleashed can fully re-flash the device over USB in DFU/recovery mode — core firmware, radio stack and FUS handling — mirroring qFlipper's Full Repair flow.
  • Release notifications. Optional push notifications for new Unleashed and official firmware releases, with a separate opt-in for dev-channel builds.

Device

  • Device info. Connected Flipper status expanded with firmware version and build date, battery details, internal/external storage state and a raw device-details sheet.
  • GPS and internet sharing. On firmware builds with the RPC GPS/network extension, the app feeds the phone's location to Flipper apps and proxies network connections from the Flipper through the phone's internet, with live TX/RX traffic stats on the device card.
  • Remote desktop. Live screen streaming and button control, physical-keyboard input on desktop, screenshot export and GIF recording of the Flipper screen.
  • Command line. A full CLI terminal session on the device (USB; not available on iOS).

Archive

  • Local-first per-device archive with synced, remote-only, local-only and deleted states, favorites, restore actions and local/remote deletion.
  • Categories. Sub-GHz, Wardriving (including autosaves), RFID 125, NFC, Infrared, iButton, Bad USB and JavaScript files.
  • Launch from the app. Saved keys can be emulated/launched on the connected Flipper straight from the archive — NFC, RFID and iButton via RPC emulation, Sub-GHz, Infrared, Bad USB and JavaScript via the matching Flipper app.
  • Editing and sharing. Built-in text editor with Flipper file-format syntax highlighting, plus sharing of remote files.
  • File Manager. Browse both /ext and /int, hidden-file visibility, folder creation, rename, delete, download, upload and direct text editing.

Apps

  • Apps catalog. Search, categories, sorting, app details and screenshots on top of the official catalog, with install, update and delete actions and detection of already-installed and preinstalled apps.

Tools

  • Pixel Draw. A pixel-art editor for the Flipper screen: project manager, multi-frame animations, dolphin animation import and live preview directly on the device display.
  • Extract MIFARE Keys. MIFARE Classic Mfkey32 key recovery from device nonces, computed natively on the phone.
  • Remotes Library. Official infrared remote source plus the public Lucaslhm/Flipper-IRDB repository: browse by brand/category, search the whole library, preview and edit .ir files, save remotes into the local archive or send them straight to /ext/infrared.
  • Pulse Plotter. Visualize raw Sub-GHz/Infrared/RFID pulse captures with zooming, histograms and slicing helpers — open captures right from the archive.
  • Saved Locations. Parses synced archive files for latitude/longitude metadata, shows them as pins on an interactive map with the current phone position, distance, bearing and walking time, and links each pin back to the saved Flipper file.

Translations

The app is translated on Crowdin. Do not edit translations/app_*.arb by hand — English is the only exception, because it is the source every other language is translated from.

Crowdin exports each language file whole, so an edit made here is not merged with the next sync, it is reverted by it. That has already cost one manual repair of the Russian translation.

  • To correct or add a translation, work in Crowdin. It reaches this repository automatically, in a pull request opened by the sync.
  • To add or change an English string, edit translations/app_en.arb. It is uploaded to Crowdin when the change lands on main, and translators see it from there.
  • To have a new language enabled, open an issue asking for it. Enabling a language is done in Crowdin; once it has translations, the sync adds translations/app_<code>.arb on its own and the app offers the locale. The only thing the repository needs is the language's own name in _localeNames (lib/services/localization/controller.dart) — without it the picker lists the language by its code rather than as Deutsch.

The Google Play listing works the same way: short_description.txt, full_description.txt and the changelogs are translated on Crowdin, so edit only the en-US copies. Screenshots, the icon, title.txt and video.txt are not on Crowdin and can be changed in any locale.

A CI check enforces all of this, so a pull request that edits a translated file fails rather than being merged and quietly undone.

Writing strings

  • Keep product names untranslated: qUnleashed, Flipper, Flipper Zero, and protocol names such as Sub-GHz, NFC, RFID, iButton.
  • Give every new key an @key description saying where it appears and, for a bare word, whether it is a verb or a noun. Translators see only the string and that description.
  • Name placeholders for what they hold ({fileName}, not {arg0}); the name is shown to translators.

Support ApertureFox projects

Boosty YooMoney

GRAM (TON): UQAntlM9gsL92ODiNxNbH4SPpfL5OpYm2gbbuNYZuE9vDEYK

Screenshots

Home screen Home screen with menu Connection screen Firmware install screen

Installed firmware screen Remote control screen Archive screen Archive category screen

File manager screen File select screen Text editor screen Apps catalog screen

App install screen Tools screen FlipperMap pins screen FlipperMap details screen

CLI tool screen Mfkey32 tool screen Infrared library screen IRDB browser screen

IRDB browser screen IRDB browser screen