AddDevbarPanel class

Serves source as a panel for as long as this widget is mounted.

The unit is the panel rather than the plugin. A devbar's plugins are declared once and live as long as it does, which is right for the things an app has all the time — its flags, its logs, its network. It is wrong for anything scoped to something the app opens and closes. A database opened at login and closed at logout has nothing to hand a devbar built at runApp, and the panel it would serve has no business existing while nobody is signed in. So it is declared where that scope is: in the widget tree.

AddDevbarPanel(
  source: _session.databasePanel,
  child: signedInApp,
)

Everything downstream already expected this. The list of panels is announced on every change and every host re-reads it, so a panel appearing mid-run reaches the cockpit's App tab, fw and MCP without any of them being told about sessions.

The same call, tied to a lifetime. This is DevbarPanels.add with the removal wired to dispose, the way AddDevbarButton wraps UiService.addButton. Reach past it to DevbarPanels when the scope is a service rather than a subtree — a session opened at login has no subtree to hang from, and inventing one costs a remount.

source is not owned here. DevbarPanelSource declares no dispose, so this cannot be the thing that disposes one — build the source where its data lives (a State, a session object) and let it die with that. Building one inside build is the same mistake as building an AnimationController there, with the same symptom: a new instance every frame, and here that means the panel is torn down and re-declared every frame.

Consider not doing this at all. A panel that comes and goes cannot explain its own absence: an agent asking for db:main is told "this app declares no panel db:main" whether the app has no database or the user simply is not signed in, and only one of those is worth acting on. A panel that is always there and answers "no session is open" keeps them apart — see DatabaseUnavailable, which is that answer for a database. Use this widget when the panel genuinely does not exist outside the scope, not merely when its data does not.

Inheritance

Constructors

AddDevbarPanel({Key? key, required DevbarPanelSource source, Widget? child})
const

Properties

child → Widget?
The subtree this panel is scoped to. Rendered unchanged — this widget adds no box, no layout and no paint, so it can be dropped in anywhere without moving anything.
final
hashCode → int
The hash code for this object.
no setterinherited
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
source → DevbarPanelSource
final

Methods

createElement() → StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() → State<AddDevbarPanel>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited