layerx_debugger 1.9.1
layerx_debugger: ^1.9.1 copied to clipboard
Drop-in debugger and logger for Flutter and GetX: pretty console logs, Dio/http capture, crash handling, route, widget and performance tracking, plus an in-app log viewer.
Changelog #
All notable changes to layerx_debugger are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.9.1 #
Fixed #
- Log attribution (screen / method) now populates from the stack. The
stack-frame parser's SDK-frame filter matched
dart:as a bare substring, which also matched every real app frame — a normal frame path ends in.dart:<line>(e.g.package:myapp/home_controller.dart:42). As a result it skipped all app frames andscreenName/methodNamewere never derived from a stack (only file/line resolved). The filter now anchors to the frame's location parens ((dart:,(package:flutter/,(package:logger/), so true SDK/framework frames are skipped while the first real app frame is attributed correctly.
1.9.0 #
Changed #
- UX P4: accessible to every tester. Every control now has a ≥48dp touch target and a screen-reader label (VoiceOver/TalkBack never announce a bare "button"). With OS reduce-motion on, nothing animates perpetually — and even without it, the floating button's pulse now fires only when a new problem arrives, then rests. A one-time coach mark introduces the "Report a bug" button on first run, empty states say plainly that the tool records what happened (redo the action in the app — there is no retry button to hunt for), and the viewer holds up under 1.5× system text scaling and RTL locales. This completes the 1.5.0 → 1.9.0 usability-first redesign arc.
1.8.0 #
Changed #
- UX P3: calm, readable, accessible. The Neo-Terminal skin is retired: a neutral high-contrast dark palette where every load-bearing text token meets WCAG AA (≥4.5:1) — enforced by a contrast unit test — with crashes/fatals as the most prominent color in the system. The shell prompt and blinking cursor are gone (plain "Debugger" title + honest problem count), monospace is reserved for payloads and stack traces, cards/pills/snackbars have visible edges, the floating button is now a labeled "Report a bug" pill, and the edge-swipe affordance is a visible handle.
1.7.0 #
Changed #
- UX P2: the debugger now tells you whose fault it is. Every problem card
leads with a plain-language verdict from the built-in blame engine (e.g.
"🖥️ Backend Server (5xx Internal Error)"), and opening a problem reads
top-to-bottom like a bug report: who to assign & why → suggested fix →
details → what the app sent → what the server answered → journey → collapsed
technical stack. A persistent Copy bug report button (with Prev/Next to
walk problems) produces a complete, paste-ready ticket. States are honest:
filtered-empty offers "Clear filters", truly-empty explains the tool records
(it can't retry), and pausing shows a full-width banner. Friendly labels
everywhere (🖥 Server Error instead of
server, relative time instead of ISO-8601, "response changed shape" instead of Δ/schema). Slow requests (≥800ms, configurable viaLayerXLogStore.slowRequestThresholdMs) now count as problems in every badge and count.
1.6.0 #
Changed #
- UX P1: the viewer now opens on a Problems inbox. The 4-tab shell is replaced by two segments — Problems (a worst-first inbox of errors, crashes, warnings, changed responses, and slow requests ≥800ms) and Everything (the full Console / Network / Dashboard, one tap away). Details open by tapping a row (the Inspector can no longer cold-open on "NOTHING SELECTED"), a labeled Done closes the viewer, Pause/Resume moved into the ⋯ menu as labeled actions, and the FAB badge / header / settings tile now all show the same number: open problems.
1.5.0 #
Changed #
- UX P0 (from the usability audit): safer, clearer, honest. One-tap
"clear all" is gone — clearing now lives behind a confirm sheet ("Start a new
session") that offers Copy report first and an Undo snackbar that
restores everything. Every copy action shows the same confirmation
("Copied — paste it into your bug report"), including the previously silent
Inspector Request/Response copy; exporting an empty session now says
"Nothing captured yet" instead of copying an empty report. The Dashboard's
AVG LATENCY card now shows the actual number (it previously rendered the
literal text "ms"). New internals: a single-issue plain-language bug-report
formatter (first wiring of
LayerXBlameEngineinto the product) andLayerXLogStore.openProblemCountas the one source of truth for problem badges.
1.4.2 #
Changed #
- The debugger is now debug/profile-only by default. When
environmentis not set explicitly, it auto-selects by build mode:LayerXEnvironment.prodin release builds (viewer/FAB off, warnings+ only) andLayerXEnvironment.devotherwise. Previously the default was alwaysdev, so a release build with the default config would show the debug FAB to end users. The FAB/viewer can no longer leak into a production release unless you opt in. Settingenvironmentexplicitly still overrides the auto-selection, and debug/profile behavior is unchanged.
1.4.1 #
Fixed #
- The debug FAB now appears on every app with zero
builder:wiring. Previously the floating debug button only showed whenLayerXDebugOverlaywas wired intoMaterialApp.builder— which the setup CLI skips whenever the app already declares abuilder:(nearly every GetX app), so the FAB was missing even though the debugger initialized. The package now inserts the FAB/edge triggers into the app's rootOverlayat runtime (driven by the route observer, kept above routes on navigation), so it works out of the box.LayerXDebugOverlaystill works for anyone who uses it, and the shared single overlay entry guarantees there is never a duplicate FAB. All overlay work is deferred and guarded so it never affects route logging or the host app.
1.4.0 #
Added #
- Viewer overhaul (Phase 2). The in-app log viewer gains: filter by
category and by level in the Console, pause / resume of live logs
from the header, a per-row copy action, and — in the Inspector — the log's
category and source
file:lineplus a collapsible stack trace. Internal UI only; no API changes.
1.3.0 #
Added #
- Unified capture (Phase 1). The in-app logs now also collect Flutter
framework/UI exceptions (build, layout, render, paint, overflow), uncaught
Dart/async/platform/isolate errors, and
print/debugPrintconsole output — all flowing through the existing pipeline. Every entry now carries aLayerXLogCategory(App Logs, Flutter Framework, UI Exceptions, Dart Exceptions, Network, API, Navigation, Lifecycle, Performance, Crash Logs, Debug Console, System Logs) and, when parseable, a source file and line. Console capture runs in debug/profile builds; release keeps errors-only with the viewer off. A reentrancy guard prevents the debugger's own console output from being re-captured. All changes are additive and backward-compatible; the existing viewer shows the new entries as normal logs (category filtering is Phase 2).
1.2.3 #
Added #
- Self-healing setup — a bad edit can no longer reach your build. The verify
step now syntax-checks every file the CLI touched (via
dart formatas a parse gate). If an injection left a file that no longer parses, it is automatically rolled back from its.bakand setup tells you to wire that spot manually, instead of leaving a non-compiling app. This is a general backstop for the regex-based source edits, so future edge cases fail safe.
1.2.2 #
Fixed #
- Setup no longer crashes on Windows during the verify step.
dart formatandflutter analyzewere launched withProcess.runwithout a shell; on Windows those tools are.batshims, so the run threw an unhandledProcessException("The system cannot find the file specified") and aborted setup right at the end. Both commands now run withrunInShell: trueand are wrapped so a launch failure degrades to a warning instead of crashing. - Setup no longer injects a duplicate
builder:intoMaterialApp/GetMaterialApp. When the app already declared its ownbuilder:(ornavigatorObservers:), the CLI still added a second one — a duplicate named argument that fails to compile. Each parameter is now injected only when the app doesn't already declare it at the top level of the constructor. When an existingbuilder:is found, it is left untouched and the CLI prints how to wrap its child withLayerXDebugOverlaymanually.
1.2.1 #
Fixed #
- Setup no longer produces invalid Dart when binding a class-level Dio
field. The auto-setup CLI used to append a separate
dio.interceptors.add(LayerXDioInterceptor());statement after the matchedDio(...)initializer. That is only valid inside a function/constructor body; when the client is a plain field — e.g.static final Dio _dio = Dio();— the statement landed in the class body, where bare statements are illegal, triggering parser errors (missing_method_parameters,expected_class_member, …). The interceptor is now attached with a cascade on the constructor itself (Dio()..interceptors.add(LayerXDioInterceptor())), which is valid both in a field initializer and inside a function body.
1.2.0 #
Changed #
- Brand-new "Neo Terminal" viewer UI. The in-app debugger was fully
restyled: a pure-black devtools console with a neon-green/cyan accent and
monospace-forward type, a terminal command-bar header with a live log count
and a blinking cursor, an animated bottom nav whose indicator slides to the
active destination, fade-through page transitions, and staggered entrance
animations on every list. Audited for zero overflow down to a 320px-wide
screen (covered by a new widget test that taps through every destination,
including mid-transition). Fixes a latent crash where issue/problem rows with
a colored left rail threw
A borderRadius can only be given on borders with uniform colorswhen painted.
Added #
LayerXHttpClient— generic capture for apps with their own HTTP client. A transparenthttp.BaseClientdecorator that wraps any inner client (a customIOClient, aRetryClient, or the defaulthttp.Client()) and logs every request/response/error with no per-call setup. Apps that route all traffic through a single client — for example alayerx_generator-generatedHttpsCallsservice — now get full API capture by changing one line:IOClient(...)→LayerXHttpClient(IOClient(...)). Multipart requests are captured too, the request is never altered, and the caller always receives an intact response.- Auto-setup now wires API capture for you.
dart run layerx_debugger:setupdetects the app's HTTP service and wraps its underlyingIOClient/http.ClientwithLayerXHttpClientin a single robust edit (paren-balanced, type-widened, idempotent), instead of the previous fragile per-call-site rewrite that failed on large generated clients. This is why in-app API logs could be missing even when the console showed them — the capture hook was never applied; now it is.
1.1.0 #
Added #
- Redesigned in-app debugger UI — A completely new bottom-navigation experience
with four destinations: Dashboard (session health score, live metric cards,
latency sparkline, recent issues), Network (request rows with method/status/
latency and
All / Errors / Slow / Δ Changedfilters), Console (all-source timeline with source filters + search), and Inspector (overview, response, request, and trace tabs, schema-diff and suggested-fix). Cyan + white brand accent. - Floating button visibility control — The FAB and edge-swipe trigger now hide automatically while the debugger is open and restore on exit, preventing duplicate buttons and overlay conflicts.
- Automatic frame-drop (jank) capture —
LayerXFrameMonitorrecords slow frames as performance warnings (rate-limited), installed automatically when performance logging is enabled. - Smarter API response handling — A
2xxresponse whoseContent-Typeclaims JSON but whose body fails to parse is now flagged as a contract violation ("Unexpected response structure") instead of passing silently as success. LayerXNetworkLogger.recordParsingError(...)— A helper to report client-side model-mapping / deserialization failures so they surface as warnings with the offending response body.- Opt-in Dio integration —
LayerXDioInterceptor, available viapackage:layerx_debugger/dio.dart, forwards Dio responses and errors to LayerX.
Changed #
- Rebuilt setup CLI — Content-based detection of the logger/HTTP services
(renamed classes are still found), idempotent marker-block injection, automatic
Dio interceptor wiring, a guided snippet fallback for unrecognized HTTP wrappers,
graceful skip when no HTTP service exists, a clear abort when no logger exists, and
a post-run
dart format+flutter analyzereport. The injected dependency version is now resolved from the package itself.
Removed #
- Legacy internal viewer screens (
LxLogListScreen,LxLogDetailScreen) and their now-unused part widgets, superseded by the new shell.
1.0.6 #
Added #
- Auto-Setup CLI & Automatic Bindings — Created a fully automated
dart run layerx_debugger:setupcommand to seamlessly inject setup parameters, wrapmain.dart, integrate overlay, and dynamically bind Logger and HTTP service configurations. - Idempotent CLI Steps — Steps are verified to be fully idempotent, preventing redundant code modifications.
- Constructor Injection Precision — Added robust parsing to safely patch Logger constructors and target classes without creating stray formatting or trailing comma syntax issues.
1.0.5 #
Added #
- Premium Dark UI Redesign — Completely redesigned the in-app log viewer from scratch with a premium, high-end dark theme.
- Added new central
LxThemedesign-token system for colors, typography, glowing overlays, cards, and animated indicators. - Redesigned
LxLogListScreenwith dark glass layout, live pulse dot, inline stats bar, custom clear confirmation dialog, and terminal-inspired empty state. - Redesigned
LxLogDetailScreenwith dark terminal aesthetics, custom syntax highlighted JSON viewer, dark schema diff tables, and custom level-based accent glow cards. - Updated widgets (
LxFabTrigger,LxEdgeTrigger,LxFilterBar,LxLogTile,LxSourceChip,LxDetailCard,LxSolutionCard,LxJourneyTimeline) to align with the premium dark theme and utilize glowing accents. - Fixed navigator context crash by implementing a robust element tree traversal engine (
LayerXDebugger.findNavigator(context)) to automatically locate the activeNavigatorStatewhen the context is above the Navigator (e.g. fromMaterialApp.builderor nested contexts).
- Added new central
1.0.4 #
Fixed #
-
Architecture detection now uses folder structure, not class names — the
dart run layerx_debugger:setupCLI previously scanned source files forLayerXController/LayerXServiceclass names, which caused false negatives on valid LayerX projects. Detection now checks for the canonical LayerX folder layout underlib/app/:lib/app/mvvm/— requiredlib/app/services/— requiredlib/app/config/,lib/app/repository/,lib/app/widgets/,lib/app/customWidgets/— optional (shown as ✓ if present, never required)
A project is considered LayerX-compliant if
lib/app/exists and at least one of the required folders is present. The abort message now also shows the exact expected folder structure to make the requirement clear.
1.0.3 #
Added #
- LayerX Architecture detector in
dart run layerx_debugger:setup— the CLI now scanslib/for LayerX signals (LayerXController,LayerXService,LayerXDebugMixin,GetMaterialApp,GetPage) before running any setup steps. If no LayerX pattern is detected, setup is aborted with a clear, color-coded terminal message directing the user to adopt the LayerX Architecture first usinglayerx_generator. Nothing is written to the project in this case — the tool is fully non-destructive on abort.
1.0.2 #
Fixed #
- Navigator context crash —
LxFabTrigger,LxEdgeTriggerandLayerXDebugger.openViewernow useNavigator.of(context, rootNavigator: true)(andshowModalBottomSheetusesuseRootNavigator: true). Previously, tapping the floating 🐛 button or swiping the edge trigger threw "Navigator operation requested with a context that does not include a Navigator" becauseLayerXDebugOverlayis placed insideMaterialApp'sbuilder:callback — which sits above theNavigatorin the widget tree. Using the root navigator bypasses this scope and resolves the crash.
1.0.1 #
Added #
dart run layerx_debugger:setupCLI — one command auto-configures LayerX Debugger in any Flutter project: injects the dependency intopubspec.yaml, runsflutter pub get, wrapsmain()withLayerXDebugger.runZonedGuarded+initialize(), and injectsLayerXDebugOverlaybuilder +navigatorObserversintoMaterialApp/GetMaterialApp. Original files are backed up as.bak. Fully idempotent — safe to re-run multiple times. An optional project path argument is also supported:dart run layerx_debugger:setup /path/to/project.
1.0.0 #
🎉 First release — in-app debugging for Flutter.
A complete, zero-boilerplate debugging ecosystem that lives inside your running app:
one LayerXDebugger.initialize() call wires up logging, network capture, crash handling,
GetX integration and a full in-app log viewer.
Added #
- In-app viewer — draggable floating button, edge-swipe and
LayerXDebugSettingsButton, plusLayerXDebugger.openViewer(context)to open it from any button. Searchable, filterable, color-coded log list with a session-health banner and a rich detail screen. - "Who owns this bug?" blame engine — attributes each failure to app / backend / network with a QA-ready note, a suggested fix, and a step-by-step journey timeline.
- API response diffing — detects when a backend changes its JSON shape and renders a field-level diff (added / removed / type-changed / value-changed).
- Logging —
LayerXLog.d/i/w/e/s(+v,wtf),LayerXLog.screen(),LayerXLog.action(), structuredlog(...),apiError(...), andObject.logD()/logE()/...extensions. Colored, emoji-tagged console output with boxed┌─ │ └API blocks; auto-disabled in production. - One-call setup & detection — applies config, installs crash handling, and (in a LayerX/GetX app) auto-registers the LayerX GetX services with duplicate-prevention and a double-initialization guard. Best-effort architecture detection activates modules incrementally and prints a status banner.
- Auto-injected GetX services —
LayerXLoggerService,LayerXDebugService,LayerXCrashService,LayerXNetworkService,LayerXPerformanceService,LayerXRouteService(viaLayerXBindings). - Networking —
httpis the primary integration viaLayerXHttp(get/post/put/patch/delete) and the sharedLayerXNetworkLogger; sensitive fields are masked (********). Dio is supported optionally via a documented interceptor recipe — no forceddiodependency. - Crash handling — global
FlutterError,PlatformDispatcherand zone capture, with anonCrashhook for optional Firebase Crashlytics / Sentry forwarding. - GetX —
LayerXController,LayerXService,LayerXDebugMixin, andLayerXRouteMiddleware;LayerXRouteObserverfornavigatorObservers. - Performance & widgets —
LayerXProfiler.start/end/measure(name, fn)and theLayerXDebugWidget(tag:)rebuild counter. - Configuration —
LayerXDebugConfigwith per-feature toggles, sensitive-key masking,LayerXEnvironment(dev/staging/prod) verbosity,autoInjectandisLayerXArchitecture.