Delete legacy inspector (#9782)
diff --git a/packages/devtools_app/integration_test/test/live_connection/eval_utils.dart b/packages/devtools_app/integration_test/test/live_connection/eval_utils.dart
index 83043cd..7e554e8 100644
--- a/packages/devtools_app/integration_test/test/live_connection/eval_utils.dart
+++ b/packages/devtools_app/integration_test/test/live_connection/eval_utils.dart
@@ -73,7 +73,7 @@
   Future<void> selectWidgetTreeNode(Finder finder) async {
     await tapAndPump(
       find.descendant(
-        of: find.byKey(InspectorScreenBodyState.summaryTreeKey),
+        of: find.byKey(InspectorScreenBodyState.inspectorTreeKey),
         matching: finder,
       ),
     );
diff --git a/packages/devtools_app/lib/devtools_app.dart b/packages/devtools_app/lib/devtools_app.dart
index 5917216..58e62b5 100644
--- a/packages/devtools_app/lib/devtools_app.dart
+++ b/packages/devtools_app/lib/devtools_app.dart
@@ -24,11 +24,11 @@
 export 'src/screens/deep_link_validation/deep_links_screen.dart';
 export 'src/screens/dtd/dtd_tools_controller.dart';
 export 'src/screens/dtd/dtd_tools_screen.dart';
-export 'src/screens/inspector/inspector_controller.dart';
-export 'src/screens/inspector/inspector_screen_body.dart';
-export 'src/screens/inspector/inspector_tree_controller.dart';
-export 'src/screens/inspector_shared/inspector_screen.dart';
-export 'src/screens/inspector_shared/inspector_screen_controller.dart';
+export 'src/screens/inspector_v2/inspector_controller.dart';
+export 'src/screens/inspector_v2/inspector_screen.dart';
+export 'src/screens/inspector_v2/inspector_screen_body.dart';
+export 'src/screens/inspector_v2/inspector_screen_controller.dart';
+export 'src/screens/inspector_v2/inspector_tree_controller.dart';
 export 'src/screens/logging/log_details_controller.dart';
 export 'src/screens/logging/logging_controller.dart';
 export 'src/screens/logging/logging_screen.dart';
@@ -76,7 +76,7 @@
 export 'src/shared/charts/treemap.dart';
 export 'src/shared/console/console_service.dart';
 export 'src/shared/console/eval/eval_service.dart';
-export 'src/shared/console/eval/inspector_tree.dart';
+export 'src/shared/console/eval/inspector_tree_v2.dart';
 export 'src/shared/console/primitives/simple_items.dart';
 export 'src/shared/console/widgets/description.dart';
 export 'src/shared/diagnostics/diagnostics_node.dart';
diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart
index 43c72cd..fdbd780 100644
--- a/packages/devtools_app/lib/src/app.dart
+++ b/packages/devtools_app/lib/src/app.dart
@@ -31,8 +31,8 @@
 import 'screens/deep_link_validation/deep_links_screen.dart';
 import 'screens/dtd/dtd_tools_controller.dart';
 import 'screens/dtd/dtd_tools_screen.dart';
-import 'screens/inspector_shared/inspector_screen.dart';
-import 'screens/inspector_shared/inspector_screen_controller.dart';
+import 'screens/inspector_v2/inspector_screen.dart';
+import 'screens/inspector_v2/inspector_screen_controller.dart';
 import 'screens/logging/logging_controller.dart';
 import 'screens/logging/logging_screen.dart';
 import 'screens/memory/framework/memory_controller.dart';
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart
deleted file mode 100644
index f5db041..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_breadcrumbs.dart
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../shared/console/eval/inspector_tree.dart';
-import '../../shared/primitives/diagnostics_text_styles.dart';
-import '../../shared/primitives/utils.dart';
-import '../../shared/ui/common_widgets.dart';
-
-class InspectorBreadcrumbNavigator extends StatelessWidget {
-  const InspectorBreadcrumbNavigator({
-    super.key,
-    required this.items,
-    required this.onTap,
-  });
-
-  /// Max number of visible breadcrumbs including root item but not 'more' item.
-  /// E.g. value 5 means root and 4 breadcrumbs can be displayed, other
-  /// breadcrumbs (if any) will be replaced by '...' item.
-  static const _maxNumberOfBreadcrumbs = 5;
-
-  final List<InspectorTreeNode> items;
-  final void Function(InspectorTreeNode?) onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    if (items.isEmpty) {
-      return const SizedBox();
-    }
-
-    final breadcrumbs = _generateBreadcrumbs(items);
-    return SizedBox(
-      height: Breadcrumb.height,
-      child: Padding(
-        padding: const EdgeInsets.symmetric(horizontal: 6),
-        child: Row(
-          children: breadcrumbs.map((item) {
-            if (item.isChevron) {
-              return const Icon(Icons.chevron_right, size: defaultIconSize);
-            }
-
-            return Flexible(
-              child: _InspectorBreadcrumb(
-                data: item,
-                onTap: () => onTap(item.node),
-              ),
-            );
-          }).toList(),
-        ),
-      ),
-    );
-  }
-
-  List<_InspectorBreadcrumbData> _generateBreadcrumbs(
-    List<InspectorTreeNode> nodes,
-  ) {
-    final lastNode = nodes.safeLast;
-    final items = nodes.map((node) {
-      return _InspectorBreadcrumbData.wrap(
-        node: node,
-        isSelected: node == lastNode,
-      );
-    }).toList();
-    List<_InspectorBreadcrumbData> breadcrumbs;
-    breadcrumbs = items.length > _maxNumberOfBreadcrumbs
-        ? [
-            items[0],
-            _InspectorBreadcrumbData.more(),
-            ...items.sublist(
-              items.length - _maxNumberOfBreadcrumbs + 1,
-              items.length,
-            ),
-          ]
-        : items;
-
-    return breadcrumbs.joinWith(_InspectorBreadcrumbData.chevron());
-  }
-}
-
-class _InspectorBreadcrumb extends StatelessWidget {
-  const _InspectorBreadcrumb({required this.data, required this.onTap});
-
-  static const _iconScale = 0.75;
-
-  final _InspectorBreadcrumbData data;
-  final VoidCallback onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    final text = Text(
-      data.text,
-      maxLines: 1,
-      overflow: TextOverflow.ellipsis,
-      style: DiagnosticsTextStyles.regular(
-        Theme.of(context).colorScheme,
-      ).copyWith(fontSize: 11),
-    );
-
-    final icon = data.icon == null
-        ? null
-        : Transform.scale(
-            scale: _iconScale,
-            child: Padding(
-              padding: const EdgeInsets.only(right: iconPadding),
-              child: data.icon,
-            ),
-          );
-
-    return InkWell(
-      onTap: data.isClickable ? onTap : null,
-      borderRadius: defaultBorderRadius,
-      child: Container(
-        padding: const EdgeInsets.symmetric(
-          horizontal: densePadding,
-          vertical: borderPadding,
-        ),
-        decoration: BoxDecoration(
-          borderRadius: defaultBorderRadius,
-          color: data.isSelected
-              ? Theme.of(context).colorScheme.selectedRowBackgroundColor
-              : Colors.transparent,
-        ),
-        child: Row(
-          mainAxisSize: MainAxisSize.min,
-          children: [
-            if (icon != null) icon,
-            Flexible(child: text),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-class _InspectorBreadcrumbData {
-  const _InspectorBreadcrumbData._({
-    required this.node,
-    required this.isSelected,
-    required this.alternativeText,
-    required this.alternativeIcon,
-  });
-
-  factory _InspectorBreadcrumbData.wrap({
-    required InspectorTreeNode node,
-    required bool isSelected,
-  }) {
-    return _InspectorBreadcrumbData._(
-      node: node,
-      isSelected: isSelected,
-      alternativeText: null,
-      alternativeIcon: null,
-    );
-  }
-
-  /// Construct a special item for showing '…' symbol between other items
-  factory _InspectorBreadcrumbData.more() {
-    return const _InspectorBreadcrumbData._(
-      node: null,
-      isSelected: false,
-      alternativeText: _ellipsisValue,
-      alternativeIcon: null,
-    );
-  }
-
-  factory _InspectorBreadcrumbData.chevron() {
-    return const _InspectorBreadcrumbData._(
-      node: null,
-      isSelected: false,
-      alternativeText: null,
-      alternativeIcon: _breadcrumbSeparatorIcon,
-    );
-  }
-
-  static const _ellipsisValue = '…';
-  static const _breadcrumbSeparatorIcon = Icons.chevron_right;
-
-  final InspectorTreeNode? node;
-  final IconData? alternativeIcon;
-  final String? alternativeText;
-  final bool isSelected;
-
-  String get text => alternativeText ?? node?.diagnostic?.description ?? '';
-
-  Widget? get icon {
-    if (alternativeIcon != null) {
-      return const Icon(_breadcrumbSeparatorIcon, size: defaultIconSize);
-    }
-
-    return node?.diagnostic?.icon;
-  }
-
-  bool get isChevron =>
-      node == null && alternativeIcon == _breadcrumbSeparatorIcon;
-
-  bool get isEllipsis => node == null && alternativeText == _ellipsisValue;
-
-  bool get isClickable => !isSelected && !isEllipsis;
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart
deleted file mode 100644
index 9ddc819..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart
+++ /dev/null
@@ -1,950 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-/// This library must not have direct dependencies on dart:html.
-///
-/// This allows tests of the complicated logic in this class to run on the VM
-/// and will help simplify porting this code to work with Hummingbird.
-///
-/// This code is directly based on
-/// src/io/flutter/view/InspectorPanel.java
-/// with some refactors to make the code more of a controller than a combination
-/// of view and controller. View specific portions of InspectorPanel.java have
-/// been moved to inspector.dart.
-library;
-
-import 'dart:async';
-
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:logging/logging.dart';
-import 'package:vm_service/vm_service.dart';
-
-import '../../service/service_extensions.dart' as extensions;
-import '../../shared/analytics/analytics.dart' as ga;
-import '../../shared/analytics/constants.dart' as gac;
-import '../../shared/analytics/metrics.dart';
-import '../../shared/console/eval/inspector_tree.dart';
-import '../../shared/console/primitives/simple_items.dart';
-import '../../shared/diagnostics/diagnostics_node.dart';
-import '../../shared/diagnostics/inspector_service.dart';
-import '../../shared/diagnostics/primitives/instance_ref.dart';
-import '../../shared/globals.dart';
-import '../../shared/primitives/query_parameters.dart';
-import '../../shared/primitives/utils.dart';
-import '../../shared/utils/utils.dart';
-import '../inspector_shared/inspector_screen.dart';
-import 'inspector_tree_controller.dart';
-
-final _log = Logger('inspector_controller');
-
-/// This class is based on the InspectorPanel class from the Flutter IntelliJ
-/// plugin with some refactors to make it more of a true controller than a view.
-class InspectorController extends DisposableController
-    with AutoDisposeControllerMixin
-    implements InspectorServiceClient {
-  InspectorController({
-    required this.inspectorTree,
-    InspectorTreeController? detailsTree,
-    required this.treeType,
-    this.parent,
-    this.isSummaryTree = true,
-  }) : assert((detailsTree != null) == isSummaryTree) {
-    unawaited(_init(detailsTree: detailsTree));
-  }
-
-  Future<void> _init({InspectorTreeController? detailsTree}) async {
-    _refreshRateLimiter = RateLimiter(refreshFramesPerSecond, refresh);
-
-    inspectorTree.config = InspectorTreeConfig(
-      onNodeAdded: _onNodeAdded,
-      onSelectionChange: selectionChanged,
-      onExpand: _onExpand,
-      onClientActiveChange: _onClientChange,
-    );
-    details = isSummaryTree
-        ? InspectorController(
-            inspectorTree: detailsTree!,
-            treeType: treeType,
-            parent: this,
-            isSummaryTree: false,
-          )
-        : null;
-
-    await serviceConnection.serviceManager.onServiceAvailable;
-
-    if (inspectorService is InspectorService) {
-      _treeGroups = InspectorObjectGroupManager(
-        serviceConnection.inspectorService as InspectorService,
-        'tree',
-      );
-      _selectionGroups = InspectorObjectGroupManager(
-        serviceConnection.inspectorService as InspectorService,
-        'selection',
-      );
-    }
-
-    addAutoDisposeListener(
-      serviceConnection.serviceManager.isolateManager.mainIsolate,
-      () {
-        final isolate =
-            serviceConnection.serviceManager.isolateManager.mainIsolate.value;
-        if (isolate != _mainIsolate) {
-          onIsolateStopped();
-        }
-        _mainIsolate = isolate;
-      },
-    );
-
-    // This logic only needs to be run once so run it in the outermost
-    // controller.
-    if (parent == null) {
-      // If select mode is available, enable the on device inspector as it
-      // won't interfere with users.
-      addAutoDisposeListener(_supportsToggleSelectWidgetMode, () {
-        if (_supportsToggleSelectWidgetMode.value) {
-          safeUnawaited(
-            serviceConnection.serviceManager.serviceExtensionManager
-                .setServiceExtensionState(
-                  extensions.enableOnDeviceInspector.extension,
-                  enabled: true,
-                  value: true,
-                ),
-          );
-        }
-      });
-    }
-
-    addAutoDisposeListener(serviceConnection.serviceManager.connectedState, () {
-      if (serviceConnection.serviceManager.connectedState.value.connected) {
-        _handleConnectionStart();
-      } else {
-        _handleConnectionStop();
-      }
-    });
-
-    if (serviceConnection.serviceManager.connectedAppInitialized) {
-      _handleConnectionStart();
-    }
-
-    serviceConnection.consoleService.ensureServiceInitialized();
-  }
-
-  void _handleConnectionStart() {
-    // Clear any existing badge/errors for older errors that were collected.
-    // Do this in a post frame callback so that we are not trying to clear the
-    // error notifiers for this screen while the framework is already in the
-    // process of building widgets.
-    // TODO(kenz): When this method is called outside  createState(), this post
-    // frame callback can be removed.
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      serviceConnection.errorBadgeManager.clearErrorCount(InspectorScreen.id);
-    });
-    filterErrors();
-  }
-
-  void _handleConnectionStop() {
-    setActivate(false);
-    if (isSummaryTree) {
-      dispose();
-    }
-  }
-
-  IsolateRef? _mainIsolate;
-
-  ValueListenable<bool> get _supportsToggleSelectWidgetMode => serviceConnection
-      .serviceManager
-      .serviceExtensionManager
-      .hasServiceExtension(extensions.toggleSelectWidgetMode.extension);
-
-  void _onClientChange(bool added) {
-    if (!added && _clientCount == 0) {
-      // Don't try to remove clients if there are none
-      return;
-    }
-
-    _clientCount += added ? 1 : -1;
-    assert(_clientCount >= 0);
-    if (_clientCount == 1) {
-      setVisibleToUser(true);
-      setActivate(true);
-    } else if (_clientCount == 0) {
-      setVisibleToUser(false);
-    }
-  }
-
-  int _clientCount = 0;
-
-  /// Maximum frame rate to refresh the inspector at to avoid taxing the
-  /// physical device with too many requests to recompute properties and trees.
-  ///
-  /// A value up to around 30 frames per second could be reasonable for
-  /// debugging highly interactive cases particularly when the user is on a
-  /// simulator or high powered native device. The frame rate is set low
-  /// for now mainly to minimize risk.
-  static const refreshFramesPerSecond = 5.0;
-
-  final bool isSummaryTree;
-
-  /// Parent InspectorController if this is a details subtree.
-  InspectorController? parent;
-
-  InspectorController? details;
-
-  InspectorTreeController inspectorTree;
-  final FlutterTreeType treeType;
-
-  late RateLimiter _refreshRateLimiter;
-
-  InspectorServiceBase get inspectorService =>
-      serviceConnection.inspectorService as InspectorServiceBase;
-
-  /// Groups used to manage and cancel requests to load data to display directly
-  /// in the tree.
-  InspectorObjectGroupManager? _treeGroups;
-
-  /// Groups used to manage and cancel requests to determine what the current
-  /// selection is.
-  ///
-  /// This group needs to be kept separate from treeGroups as the selection is
-  /// shared more with the details subtree.
-  /// TODO(jacobr): is there a way we can unify the selection and tree groups?
-  InspectorObjectGroupManager? _selectionGroups;
-
-  /// Node being highlighted due to the current hover.
-  InspectorTreeNode? get currentShowNode => inspectorTree.hover;
-
-  set currentShowNode(InspectorTreeNode? node) => inspectorTree.hover = node;
-
-  bool flutterAppFrameReady = false;
-
-  bool treeLoadStarted = false;
-
-  RemoteDiagnosticsNode? subtreeRoot;
-
-  bool programmaticSelectionChangeInProgress = false;
-
-  ValueListenable<InspectorTreeNode?> get selectedNode => _selectedNode;
-  final _selectedNode = ValueNotifier<InspectorTreeNode?>(null);
-
-  InspectorTreeNode? lastExpanded;
-
-  bool isActive = false;
-
-  final valueToInspectorTreeNode = <InspectorInstanceRef, InspectorTreeNode>{};
-
-  /// When visibleToUser is false we should dispose all allocated objects and
-  /// not perform any actions.
-  bool visibleToUser = false;
-
-  bool highlightNodesShownInBothTrees = false;
-
-  bool get detailsSubtree => parent != null;
-
-  RemoteDiagnosticsNode? get selectedDiagnostic =>
-      selectedNode.value?.diagnostic;
-
-  ValueListenable<int?> get selectedErrorIndex => _selectedErrorIndex;
-  final _selectedErrorIndex = ValueNotifier<int?>(null);
-
-  /// Tracks whether the first load of the inspector tree has been completed.
-  ///
-  /// This field is used to prevent sending multiple analytics events for
-  /// inspector tree load timing.
-  bool firstInspectorTreeLoadCompleted = false;
-
-  FlutterTreeType getTreeType() {
-    return treeType;
-  }
-
-  void setVisibleToUser(bool visible) {
-    if (visibleToUser == visible) {
-      return;
-    }
-    visibleToUser = visible;
-
-    if (visibleToUser) {
-      if (parent == null) {
-        unawaited(maybeLoadUI());
-      }
-    } else {
-      shutdownTree(false);
-    }
-  }
-
-  bool hasDiagnosticsValue(InspectorInstanceRef ref) {
-    return valueToInspectorTreeNode.containsKey(ref);
-  }
-
-  RemoteDiagnosticsNode? findDiagnosticsValue(InspectorInstanceRef ref) {
-    return valueToInspectorTreeNode[ref]?.diagnostic;
-  }
-
-  void endShowNode() {
-    highlightShowNode(null);
-  }
-
-  bool highlightShowFromNodeInstanceRef(InspectorInstanceRef ref) {
-    return highlightShowNode(valueToInspectorTreeNode[ref]);
-  }
-
-  bool highlightShowNode(InspectorTreeNode? node) {
-    if (node == null && parent != null) {
-      // If nothing is highlighted, highlight the node selected in the parent
-      // tree so user has context of where the node selected in the parent is
-      // in the details tree.
-      node = findMatchingInspectorTreeNode(parent?.selectedDiagnostic);
-    }
-
-    currentShowNode = node;
-    return true;
-  }
-
-  InspectorTreeNode? findMatchingInspectorTreeNode(
-    RemoteDiagnosticsNode? node,
-  ) {
-    final valueRef = node?.valueRef;
-    if (valueRef == null) {
-      return null;
-    }
-    return valueToInspectorTreeNode[valueRef];
-  }
-
-  Future<void> _waitForPendingUpdateDone() async {
-    // Wait for the selection to be resolved followed by waiting for the tree to be computed.
-    await _selectionGroups?.pendingUpdateDone;
-    await _treeGroups?.pendingUpdateDone;
-    // TODO(jacobr): are there race conditions we need to think more carefully about here?
-  }
-
-  Future<void> refresh() {
-    if (!visibleToUser) {
-      // We will refresh again once we are visible.
-      // There is a risk a refresh got triggered before the view was visble.
-      return Future.value();
-    }
-
-    // TODO(jacobr): refresh the tree as well as just the properties.
-    final detailsLocal = details;
-    if (detailsLocal == null) return _waitForPendingUpdateDone();
-
-    return [
-      _waitForPendingUpdateDone(),
-      detailsLocal._waitForPendingUpdateDone(),
-    ].wait;
-  }
-
-  // Note that this may be called after the controller is disposed.  We need to handle nulls in the fields.
-  void shutdownTree(bool isolateStopped) {
-    // It is critical we clear all data that is kept alive by inspector object
-    // references in this method as that stale data will trigger inspector
-    // exceptions.
-    programmaticSelectionChangeInProgress = true;
-    _treeGroups?.clear(isolateStopped);
-    _selectionGroups?.clear(isolateStopped);
-
-    currentShowNode = null;
-    _selectedNode.value = null;
-    lastExpanded = null;
-
-    subtreeRoot = null;
-
-    inspectorTree.root = inspectorTree.createNode();
-    programmaticSelectionChangeInProgress = false;
-    valueToInspectorTreeNode.clear();
-  }
-
-  void onIsolateStopped() {
-    flutterAppFrameReady = false;
-    treeLoadStarted = false;
-    shutdownTree(true);
-  }
-
-  @override
-  Future<void> onForceRefresh() async {
-    assert(!disposed);
-    if (!visibleToUser || disposed) {
-      return;
-    }
-    await _recomputeTreeRoot(null, null, false);
-    if (disposed) {
-      return;
-    }
-
-    filterErrors();
-
-    return _waitForPendingUpdateDone();
-  }
-
-  void filterErrors() {
-    if (isSummaryTree) {
-      serviceConnection.errorBadgeManager.filterErrors(
-        InspectorScreen.id,
-        (id) => hasDiagnosticsValue(InspectorInstanceRef(id)),
-      );
-    }
-  }
-
-  void setActivate(bool enabled) {
-    if (!enabled) {
-      onIsolateStopped();
-      isActive = false;
-      return;
-    }
-    if (isActive) {
-      // Already activated.
-      return;
-    }
-
-    isActive = true;
-    inspectorService.addClient(this);
-    unawaited(maybeLoadUI());
-  }
-
-  Future<void> maybeLoadUI() async {
-    if (parent != null) {
-      // The parent controller will drive loading the UI.
-      return;
-    }
-    if (!visibleToUser || !isActive) {
-      return;
-    }
-
-    if (flutterAppFrameReady) {
-      if (disposed) return;
-      // We need to start by querying the inspector service to find out the
-      // current state of the UI.
-      final inspectorRef = DevToolsQueryParams.load().inspectorRef;
-      await updateSelectionFromService(
-        firstFrame: true,
-        inspectorRef: inspectorRef,
-      );
-    } else {
-      if (disposed) return;
-      if (inspectorService is InspectorService) {
-        final widgetTreeReady = await (inspectorService as InspectorService)
-            .isWidgetTreeReady();
-        flutterAppFrameReady = widgetTreeReady;
-      }
-      if (isActive && flutterAppFrameReady) {
-        await maybeLoadUI();
-      }
-    }
-  }
-
-  Future<void> _recomputeTreeRoot(
-    RemoteDiagnosticsNode? newSelection,
-    RemoteDiagnosticsNode? detailsSelection,
-    bool setSubtreeRoot, {
-    int subtreeDepth = 2,
-  }) async {
-    assert(!disposed);
-    final treeGroups = _treeGroups;
-    if (disposed || treeGroups == null) {
-      return;
-    }
-
-    treeGroups.cancelNext();
-    try {
-      final group = treeGroups.next;
-      final node = await (detailsSubtree
-          ? group.getDetailsSubtree(subtreeRoot, subtreeDepth: subtreeDepth)
-          : group.getRoot(treeType, isSummaryTree: true));
-      if (node == null || group.disposed || disposed) {
-        return;
-      }
-      // TODO(jacobr): as a performance optimization we should check if the
-      // new tree is identical to the existing tree in which case we should
-      // dispose the new tree and keep the old tree.
-      treeGroups.promoteNext();
-      _clearValueToInspectorTreeNodeMapping();
-
-      final rootNode = inspectorTree.setupInspectorTreeNode(
-        inspectorTree.createNode(),
-        node,
-        expandChildren: true,
-        expandProperties: false,
-      );
-      inspectorTree.root = rootNode;
-
-      refreshSelection(newSelection, detailsSelection, setSubtreeRoot);
-    } catch (error, st) {
-      _log.shout(error, error, st);
-      treeGroups.cancelNext();
-      return;
-    }
-  }
-
-  void _clearValueToInspectorTreeNodeMapping() {
-    valueToInspectorTreeNode.clear();
-  }
-
-  /// Show the details subtree starting with node subtreeRoot highlighting
-  /// node subtreeSelection.
-  void _showDetailSubtrees(
-    RemoteDiagnosticsNode? subtreeRoot,
-    RemoteDiagnosticsNode? subtreeSelection,
-  ) {
-    this.subtreeRoot = subtreeRoot;
-    details?.setSubtreeRoot(subtreeRoot, subtreeSelection);
-  }
-
-  void setSubtreeRoot(
-    RemoteDiagnosticsNode? node,
-    RemoteDiagnosticsNode? selection,
-  ) {
-    assert(detailsSubtree);
-    selection ??= node;
-    if (node != null && node == subtreeRoot) {
-      //  Select the new node in the existing subtree.
-      applyNewSelection(selection, null, false);
-      return;
-    }
-    subtreeRoot = node;
-    if (node == null) {
-      // Passing in a null node indicates we should clear the subtree and free any memory allocated.
-      shutdownTree(false);
-      return;
-    }
-
-    // Clear now to eliminate frame of highlighted nodes flicker.
-    _clearValueToInspectorTreeNodeMapping();
-    unawaited(_recomputeTreeRoot(selection, null, false));
-  }
-
-  InspectorTreeNode? getSubtreeRootNode() {
-    if (subtreeRoot == null) {
-      return null;
-    }
-    return valueToInspectorTreeNode[subtreeRoot!.valueRef];
-  }
-
-  void refreshSelection(
-    RemoteDiagnosticsNode? newSelection,
-    RemoteDiagnosticsNode? detailsSelection,
-    bool setSubtreeRoot,
-  ) {
-    newSelection ??= selectedDiagnostic;
-    setSelectedNode(findMatchingInspectorTreeNode(newSelection));
-    syncSelectionHelper(
-      maybeRerootDetailsTree: setSubtreeRoot,
-      selection: newSelection,
-      detailsSelection: detailsSelection,
-    );
-
-    final detailsLocal = details;
-    if (detailsLocal != null) {
-      if (subtreeRoot != null && getSubtreeRootNode() == null) {
-        subtreeRoot = newSelection;
-        detailsLocal.setSubtreeRoot(newSelection, detailsSelection);
-      }
-    }
-    syncTreeSelection();
-  }
-
-  void syncTreeSelection() {
-    programmaticSelectionChangeInProgress = true;
-    inspectorTree.selection = selectedNode.value;
-    inspectorTree.expandPath(selectedNode.value);
-    programmaticSelectionChangeInProgress = false;
-    animateTo(selectedNode.value);
-  }
-
-  void selectAndShowNode(RemoteDiagnosticsNode? node) {
-    if (node == null) {
-      return;
-    }
-    selectAndShowInspectorInstanceRef(node.valueRef);
-  }
-
-  void selectAndShowInspectorInstanceRef(InspectorInstanceRef ref) {
-    final node = valueToInspectorTreeNode[ref];
-    if (node == null) {
-      return;
-    }
-    setSelectedNode(node);
-    syncTreeSelection();
-  }
-
-  InspectorTreeNode? getTreeNode(RemoteDiagnosticsNode node) {
-    return valueToInspectorTreeNode[node.valueRef];
-  }
-
-  void maybeUpdateValueUI(InspectorInstanceRef valueRef) {
-    final node = valueToInspectorTreeNode[valueRef];
-    if (node == null) {
-      // The value isn't shown in the parent tree. Nothing to do.
-      return;
-    }
-    inspectorTree.nodeChanged(node);
-  }
-
-  @override
-  void onFlutterFrame() {
-    flutterAppFrameReady = true;
-    if (!visibleToUser) {
-      return;
-    }
-
-    if (!treeLoadStarted) {
-      treeLoadStarted = true;
-      // This was the first frame.
-      unawaited(maybeLoadUI());
-    }
-    _refreshRateLimiter.scheduleRequest();
-  }
-
-  @override
-  void onInspectorSelectionChanged() {
-    if (!visibleToUser) {
-      // Don't do anything. We will update the view once it is visible again.
-      return;
-    }
-    if (detailsSubtree) {
-      // Wait for the master to update.
-      return;
-    }
-    unawaited(updateSelectionFromService(firstFrame: false));
-  }
-
-  Future<void> updateSelectionFromService({
-    required bool firstFrame,
-    String? inspectorRef,
-  }) async {
-    if (parent != null) {
-      // If we have a parent controller we should wait for the parent to update
-      // our selection rather than updating it our self.
-      return;
-    }
-    final selectionGroups = _selectionGroups;
-    if (selectionGroups == null) {
-      // Already disposed. Ignore this requested to update selection.
-      return;
-    }
-    treeLoadStarted = true;
-
-    selectionGroups.cancelNext();
-
-    final group = selectionGroups.next;
-
-    if (inspectorRef != null) {
-      await group.setSelectionInspector(
-        InspectorInstanceRef(inspectorRef),
-        false,
-      );
-      if (disposed) return;
-    }
-    final pendingSelectionFuture = group.getSelection(
-      selectedDiagnostic,
-      treeType,
-      restrictToLocalProject: isSummaryTree,
-    );
-
-    final pendingDetailsFuture = isSummaryTree
-        ? group.getSelection(selectedDiagnostic, treeType)
-        : null;
-
-    try {
-      final newSelection = await pendingSelectionFuture;
-      if (disposed || group.disposed) return;
-      RemoteDiagnosticsNode? detailsSelection;
-
-      if (pendingDetailsFuture != null) {
-        detailsSelection = await pendingDetailsFuture;
-        if (disposed || group.disposed) return;
-      }
-
-      if (!firstFrame &&
-          detailsSelection?.valueRef == details?.selectedDiagnostic?.valueRef &&
-          newSelection?.valueRef == selectedDiagnostic?.valueRef) {
-        // No need to change the selection as it didn't actually change.
-        selectionGroups.cancelNext();
-        return;
-      }
-      selectionGroups.promoteNext();
-
-      subtreeRoot = newSelection;
-
-      applyNewSelection(newSelection, detailsSelection, true);
-
-      // Send an event that a widget was selected on the device.
-      ga.select(
-        gac.inspector,
-        gac.onDeviceSelection,
-        screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
-      );
-    } catch (error, st) {
-      if (selectionGroups.next == group) {
-        _log.shout(error, error, st);
-        selectionGroups.cancelNext();
-      }
-    }
-  }
-
-  void applyNewSelection(
-    RemoteDiagnosticsNode? newSelection,
-    RemoteDiagnosticsNode? detailsSelection,
-    bool setSubtreeRoot,
-  ) {
-    final nodeInTree = findMatchingInspectorTreeNode(newSelection);
-
-    if (nodeInTree == null) {
-      // The tree has probably changed since we last updated. Do a full refresh
-      // so that the tree includes the new node we care about.
-      unawaited(
-        _recomputeTreeRoot(newSelection, detailsSelection, setSubtreeRoot),
-      );
-    }
-
-    refreshSelection(newSelection, detailsSelection, setSubtreeRoot);
-  }
-
-  void animateTo(InspectorTreeNode? node) {
-    if (node == null) {
-      return;
-    }
-
-    inspectorTree.animateToTargets([node]);
-  }
-
-  void setSelectedNode(InspectorTreeNode? newSelection) {
-    if (newSelection == selectedNode.value) {
-      return;
-    }
-
-    _selectedNode.value = newSelection;
-
-    lastExpanded = null; // New selected node takes precedence.
-    endShowNode();
-    final detailsLocal = details;
-    final parantLocal = parent;
-    if (detailsLocal != null) {
-      detailsLocal.endShowNode();
-    } else if (parantLocal != null) {
-      parantLocal.endShowNode();
-    }
-
-    _updateSelectedErrorFromNode(_selectedNode.value);
-    animateTo(selectedNode.value);
-  }
-
-  /// Update the index of the selected error based on a node that has been
-  /// selected in the tree.
-  void _updateSelectedErrorFromNode(InspectorTreeNode? node) {
-    final inspectorRef = node?.diagnostic?.valueRef.id;
-
-    final errors = serviceConnection.errorBadgeManager
-        .erroredItemsForPage(InspectorScreen.id)
-        .value;
-
-    // Check whether the node that was just selected has any errors associated
-    // with it.
-    var errorIndex = inspectorRef != null
-        ? errors.keys.toList().indexOf(inspectorRef)
-        : null;
-    if (errorIndex == -1) {
-      errorIndex = null;
-    }
-
-    _selectedErrorIndex.value = errorIndex;
-
-    if (errorIndex != null) {
-      // Mark the error as "seen" as this will render slightly differently
-      // so the user can track which errored nodes they've viewed.
-      serviceConnection.errorBadgeManager.markErrorAsRead(
-        InspectorScreen.id,
-        errors[inspectorRef!]!,
-      );
-      // Also clear the error badge since new errors may have arrived while
-      // the inspector was visible (normally they're cleared when visiting
-      // the screen) and visiting an errored node seems an appropriate
-      // acknowledgement of the errors.
-      serviceConnection.errorBadgeManager.clearErrorCount(InspectorScreen.id);
-    }
-  }
-
-  /// Updates the index of the selected error and selects its node in the tree.
-  void selectErrorByIndex(int index) {
-    _selectedErrorIndex.value = index;
-
-    final errors = serviceConnection.errorBadgeManager
-        .erroredItemsForPage(InspectorScreen.id)
-        .value;
-
-    unawaited(
-      updateSelectionFromService(
-        firstFrame: false,
-        inspectorRef: errors.keys.elementAt(index),
-      ),
-    );
-  }
-
-  void _onExpand(InspectorTreeNode node) {
-    unawaited(inspectorTree.maybePopulateChildren(node));
-  }
-
-  Future<void> _addNodeToConsole(InspectorTreeNode node) async {
-    final valueRef = node.diagnostic!.valueRef;
-    final isolateRef = inspectorService.isolateRef;
-    final instanceRef = await node.diagnostic!.objectGroupApi
-        ?.toObservatoryInstanceRef(valueRef);
-    if (disposed) return;
-
-    if (instanceRef != null) {
-      await serviceConnection.consoleService.appendInstanceRef(
-        value: instanceRef,
-        diagnostic: node.diagnostic,
-        isolateRef: isolateRef,
-        forceScrollIntoView: true,
-      );
-    }
-  }
-
-  void selectionChanged() {
-    if (!visibleToUser) {
-      return;
-    }
-
-    final node = inspectorTree.selection;
-    if (node != null) {
-      unawaited(inspectorTree.maybePopulateChildren(node));
-    }
-    if (programmaticSelectionChangeInProgress) {
-      return;
-    }
-    if (node != null) {
-      setSelectedNode(node);
-      unawaited(_addNodeToConsole(node));
-
-      // Don't reroot if the selected value is already visible in the details tree.
-      final maybeReroot =
-          isSummaryTree &&
-          details != null &&
-          selectedDiagnostic != null &&
-          !details!.hasDiagnosticsValue(selectedDiagnostic!.valueRef);
-      syncSelectionHelper(
-        maybeRerootDetailsTree: maybeReroot,
-        selection: selectedDiagnostic,
-        detailsSelection: selectedDiagnostic,
-      );
-
-      if (!maybeReroot) {
-        final parantLocal = parent;
-        final detailsLocal = details;
-
-        if (isSummaryTree && detailsLocal != null) {
-          detailsLocal.selectAndShowNode(selectedDiagnostic);
-        } else if (parantLocal != null) {
-          parantLocal.selectAndShowNode(
-            firstAncestorInParentTree(selectedNode.value),
-          );
-        }
-      }
-    }
-  }
-
-  RemoteDiagnosticsNode? firstAncestorInParentTree(InspectorTreeNode? node) {
-    final parentLocal = parent;
-
-    if (parentLocal == null) {
-      return node?.diagnostic;
-    }
-    while (node != null) {
-      final diagnostic = node.diagnostic;
-      if (diagnostic != null &&
-          parentLocal.hasDiagnosticsValue(diagnostic.valueRef)) {
-        return parentLocal.findDiagnosticsValue(diagnostic.valueRef);
-      }
-      node = node.parent;
-    }
-    return null;
-  }
-
-  void syncSelectionHelper({
-    required bool maybeRerootDetailsTree,
-    required RemoteDiagnosticsNode? selection,
-    required RemoteDiagnosticsNode? detailsSelection,
-  }) {
-    if (selection != null) {
-      if (selection.isCreatedByLocalProject) {
-        _navigateTo(selection);
-      }
-    }
-    if (detailsSubtree || details == null) {
-      if (selection != null) {
-        var toSelect = selectedNode.value;
-
-        while (toSelect != null && toSelect.diagnostic!.isProperty) {
-          toSelect = toSelect.parent;
-        }
-
-        if (toSelect != null) {
-          final diagnosticToSelect = toSelect.diagnostic!;
-          unawaited(diagnosticToSelect.setSelectionInspector(true));
-        }
-      }
-    }
-
-    if (maybeRerootDetailsTree) {
-      _showDetailSubtrees(selection, detailsSelection);
-    } else if (selection != null) {
-      // We can't rely on the details tree to update the selection on the server in this case.
-      unawaited(selection.setSelectionInspector(true));
-    }
-  }
-
-  // TODO(jacobr): implement this method and use the parameter.
-  // ignore: avoid-unused-parameters
-  void _navigateTo(RemoteDiagnosticsNode diagnostic) {
-    // TODO(jacobr): dispatch an event over the inspectorService requesting a
-    //  navigate operation.
-  }
-
-  @override
-  void dispose() {
-    assert(!disposed);
-    if (serviceConnection.inspectorService != null) {
-      shutdownTree(false);
-    }
-    _treeGroups?.clear(false);
-    _treeGroups = null;
-    _selectionGroups?.clear(false);
-    _selectionGroups = null;
-    details?.dispose();
-
-    _refreshRateLimiter.dispose();
-    _selectedNode.dispose();
-    _selectedErrorIndex.dispose();
-    super.dispose();
-  }
-
-  void _onNodeAdded(
-    InspectorTreeNode node,
-    RemoteDiagnosticsNode diagnosticsNode,
-  ) {
-    final valueRef = diagnosticsNode.valueRef;
-    // Properties do not have unique values so should not go in the valueToInspectorTreeNode map.
-    if (valueRef.id != null && !diagnosticsNode.isProperty) {
-      valueToInspectorTreeNode[valueRef] = node;
-    }
-  }
-
-  Future<void> expandAllNodesInDetailsTree() async {
-    final detailsLocal = details!;
-    await detailsLocal._recomputeTreeRoot(
-      inspectorTree.selection?.diagnostic,
-      detailsLocal.inspectorTree.selection?.diagnostic ??
-          detailsLocal.inspectorTree.root?.diagnostic,
-      false,
-      subtreeDepth: maxJsInt,
-    );
-  }
-
-  void collapseDetailsToSelected() {
-    final detailsLocal = details!;
-    detailsLocal.inspectorTree.collapseToSelected();
-    detailsLocal.animateTo(detailsLocal.inspectorTree.selection);
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart
deleted file mode 100644
index a12ed91..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_data_models.dart
+++ /dev/null
@@ -1,887 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-/// @docImport 'layout_explorer/ui/overflow_indicator_painter.dart';
-library;
-
-import 'dart:math' as math;
-
-import 'package:flutter/rendering.dart';
-
-import '../../shared/diagnostics/diagnostics_node.dart';
-import '../../shared/primitives/math_utils.dart';
-import '../../shared/primitives/utils.dart';
-import 'layout_explorer/flex/utils.dart';
-
-const overflowEpsilon = 0.1;
-
-/// Compute real widget sizes into rendered sizes to be displayed on the details tab.
-/// The sum of the resulting render sizes may or may not be greater than the [maxSizeAvailable]
-/// In the case where it is greater, we should render it with scrolling capability.
-///
-/// Variables:
-/// - [sizes] : real size for widgets that want to be rendered / scaled
-/// - [smallestSize] : the smallest element in the array [sizes]
-/// - [largestSize] : the largest element in the array [sizes]
-/// - [smallestRenderSize] : render size for smallest element
-/// - [largestRenderSize] : render size for largest element
-/// - [maxSizeAvailable] : maximum size available for rendering the widget
-/// - [useMaxSizeAvailable] : flag for forcing the widget dimension to be at least [maxSizeAvailable]
-///
-/// if [useMaxSizeAvailable] is set to true,
-/// this method will ignore the largestRenderSize
-/// and compute its own largestRenderSize to force
-/// the sum of the render size to be equals to [maxSizeAvailable]
-///
-/// Formula for computing render size:
-/// ```
-/// renderSize[i] = (size[i] - smallestSize)
-///             * (largestRenderSize - smallestRenderSize)
-///             / (largestSize - smallestSize) + smallestRenderSize
-/// ```
-/// Explanation:
-/// - The computation formula for transforming size to renderSize is based on these two things:
-///   - smallest element will be rendered to [smallestRenderSize]
-///   - largest element will be rendered to [largestRenderSize]
-///   - any other size will be scaled accordingly
-/// - The formula above is derived from:
-///   ```
-///   (renderSize[i] - smallestRenderSize) / (largestRenderSize - smallestRenderSize)
-///    = (size[i] - smallestSize) / (size[i] - smallestSize)
-///   ```
-///
-/// Formula for computing forced [largestRenderSize]:
-/// ```
-/// largestRenderSize = (maxSizeAvailable - sizes.length * smallestRenderSize)
-///   * (largestSize - smallestSize) / sum(s[i] - ss) + smallestRenderSize
-/// ```
-/// Explanation:
-/// - This formula is derived from the equation:
-///   ```
-///   sum(renderSize) = maxSizeAvailable
-///   ```
-List<double> computeRenderSizes({
-  required Iterable<double> sizes,
-  required double smallestSize,
-  required double largestSize,
-  required double smallestRenderSize,
-  required double largestRenderSize,
-  required double maxSizeAvailable,
-  bool useMaxSizeAvailable = true,
-}) {
-  final n = sizes.length;
-
-  if (smallestSize == largestSize) {
-    // It means that all widget have the same size
-    // and we can just divide the size evenly
-    // but it should be at least as big as [smallestRenderSize]
-    final renderSize = math.max(smallestRenderSize, maxSizeAvailable / n);
-    return [for (final _ in sizes) renderSize];
-  }
-
-  List<double> transformToRenderSize(double largestRenderSize) => [
-    for (final s in sizes)
-      (s - smallestSize) *
-              (largestRenderSize - smallestRenderSize) /
-              (largestSize - smallestSize) +
-          smallestRenderSize,
-  ];
-
-  var renderSizes = transformToRenderSize(largestRenderSize);
-
-  if (useMaxSizeAvailable && sum(renderSizes) < maxSizeAvailable) {
-    largestRenderSize =
-        (maxSizeAvailable - n * smallestRenderSize) *
-            (largestSize - smallestSize) /
-            sum([for (final s in sizes) s - smallestSize]) +
-        smallestRenderSize;
-    renderSizes = transformToRenderSize(largestRenderSize);
-  }
-  return renderSizes;
-}
-
-// TODO(albertusangga): Move this to [RemoteDiagnosticsNode] once dart:html app is removed
-/// Represents parsed layout information for a specific [RemoteDiagnosticsNode].
-class LayoutProperties {
-  LayoutProperties(this.node, {int copyLevel = 1})
-    : description = node.description,
-      size = node.size!,
-      constraints = node.constraints,
-      isFlex = node.isFlex,
-      flexFactor = node.flexFactor,
-      flexFit = node.flexFit,
-      children = copyLevel == 0
-          ? []
-          : node.childrenNow
-                .map(
-                  (child) => LayoutProperties(child, copyLevel: copyLevel - 1),
-                )
-                .toList(growable: false) {
-    for (final child in children) {
-      child.parent = this;
-    }
-  }
-
-  LayoutProperties.values({
-    required this.node,
-    required this.children,
-    required this.constraints,
-    required this.description,
-    required this.flexFactor,
-    required this.isFlex,
-    required this.size,
-    required this.flexFit,
-  }) {
-    for (final child in children) {
-      child.parent = this;
-    }
-  }
-
-  LayoutProperties? parent;
-  final RemoteDiagnosticsNode node;
-  final List<LayoutProperties> children;
-  final BoxConstraints? constraints;
-  final String? description;
-  final num? flexFactor;
-  final FlexFit? flexFit;
-  final bool isFlex;
-  final Size size;
-
-  /// Represents the order of [children] to be displayed.
-  List<LayoutProperties> get displayChildren => children;
-
-  bool get hasFlexFactor {
-    final flexFactorLocal = flexFactor;
-    if (flexFactorLocal == null) return false;
-    return flexFactorLocal > 0;
-  }
-
-  int get totalChildren => children.length;
-
-  bool get hasChildren => children.isNotEmpty;
-
-  double get width => size.width;
-
-  double get height => size.height;
-
-  double dimension(Axis axis) => axis == Axis.horizontal ? width : height;
-
-  List<double> childrenDimensions(Axis axis) {
-    return displayChildren.map((child) => child.dimension(axis)).toList();
-  }
-
-  List<double> get childrenWidths => childrenDimensions(Axis.horizontal);
-
-  List<double> get childrenHeights => childrenDimensions(Axis.vertical);
-
-  String describeWidthConstraints() {
-    final constraintsLocal = constraints;
-    if (constraintsLocal == null) return '';
-    return constraintsLocal.hasBoundedWidth
-        ? describeAxis(
-            constraintsLocal.minWidth,
-            constraintsLocal.maxWidth,
-            'w',
-          )
-        : 'width is unconstrained';
-  }
-
-  String describeHeightConstraints() {
-    final constraintsLocal = constraints;
-    if (constraintsLocal == null) return '';
-    return constraintsLocal.hasBoundedHeight
-        ? describeAxis(
-            constraintsLocal.minHeight,
-            constraintsLocal.maxHeight,
-            'h',
-          )
-        : 'height is unconstrained';
-  }
-
-  String describeWidth() => 'w=${toStringAsFixed(size.width)}';
-
-  String describeHeight() => 'h=${toStringAsFixed(size.height)}';
-
-  bool get isOverflowWidth {
-    final parentWidth = parent?.width;
-    if (parentWidth == null) return false;
-    final parentData = node.parentData;
-    double widthUsed = width;
-
-    widthUsed += parentData.offset.dx;
-
-    // TODO(jacobr): certain widgets may allow overflow so this may false
-    // positive a bit for cases like Stack.
-    return widthUsed > parentWidth + overflowEpsilon;
-  }
-
-  bool get isOverflowHeight {
-    final parentHeight = parent?.height;
-    if (parentHeight == null) return false;
-    final parentData = node.parentData;
-    double heightUsed = height;
-
-    heightUsed += parentData.offset.dy;
-
-    return heightUsed > parentHeight + overflowEpsilon;
-  }
-
-  static String describeAxis(double min, double max, String axis) {
-    if (min == max) return '$axis=${min.toStringAsFixed(1)}';
-    return '${min.toStringAsFixed(1)}<=$axis<=${max.toStringAsFixed(1)}';
-  }
-
-  LayoutProperties copyWith({
-    List<LayoutProperties>? children,
-    BoxConstraints? constraints,
-    String? description,
-    int? flexFactor,
-    FlexFit? flexFit,
-    bool? isFlex,
-    Size? size,
-  }) {
-    return LayoutProperties.values(
-      node: node,
-      children: children ?? this.children,
-      constraints: constraints ?? this.constraints,
-      description: description ?? this.description,
-      flexFactor: flexFactor ?? this.flexFactor,
-      isFlex: isFlex ?? this.isFlex,
-      size: size ?? this.size,
-      flexFit: flexFit ?? this.flexFit,
-    );
-  }
-}
-
-/// Enum object to represent which side of the widget is overflowing.
-///
-/// See also:
-/// * [OverflowIndicatorPainter]
-enum OverflowSide { right, bottom }
-
-// TODO(jacobr): is it possible to overflow on multiple sides?
-// TODO(jacobr): do we need to worry about overflowing on the left side in RTL
-// layouts? We need to audit the Flutter semantics for determining overflow to
-// make sure we are consistent.
-extension LayoutPropertiesExtension on LayoutProperties {
-  OverflowSide? get overflowSide {
-    if (isOverflowWidth) return OverflowSide.right;
-    if (isOverflowHeight) return OverflowSide.bottom;
-    return null;
-  }
-}
-
-final _flexLayoutExpando = Expando<FlexLayoutProperties>();
-
-extension MainAxisAlignmentExtension on MainAxisAlignment {
-  MainAxisAlignment get reversed {
-    switch (this) {
-      case MainAxisAlignment.start:
-        return MainAxisAlignment.end;
-      case MainAxisAlignment.end:
-        return MainAxisAlignment.start;
-      default:
-        return this;
-    }
-  }
-}
-
-/// TODO(albertusangga): Move this to [RemoteDiagnosticsNode] once dart:html app is removed.
-class FlexLayoutProperties extends LayoutProperties {
-  FlexLayoutProperties({
-    required super.size,
-    required super.children,
-    required super.node,
-    super.constraints,
-    super.isFlex = false,
-    super.description,
-    super.flexFactor,
-    super.flexFit,
-    this.direction = Axis.vertical,
-    this.mainAxisAlignment,
-    this.crossAxisAlignment,
-    this.mainAxisSize,
-    required this.textDirection,
-    required this.verticalDirection,
-    this.textBaseline,
-  }) : super.values();
-
-  FlexLayoutProperties._fromNode(
-    super.node, {
-    this.direction = Axis.vertical,
-    this.mainAxisAlignment,
-    this.mainAxisSize,
-    this.crossAxisAlignment,
-    required this.textDirection,
-    required this.verticalDirection,
-    this.textBaseline,
-  });
-
-  factory FlexLayoutProperties.fromDiagnostics(RemoteDiagnosticsNode node) {
-    // Cache the properties on an expando so that local tweaks to
-    // FlexLayoutProperties persist across multiple lookups from an
-    // RemoteDiagnosticsNode.
-    return _flexLayoutExpando[node] ??= _buildNode(node);
-  }
-
-  @override
-  FlexLayoutProperties copyWith({
-    Size? size,
-    List<LayoutProperties>? children,
-    BoxConstraints? constraints,
-    bool? isFlex,
-    String? description,
-    num? flexFactor,
-    FlexFit? flexFit,
-    Axis? direction,
-    MainAxisAlignment? mainAxisAlignment,
-    MainAxisSize? mainAxisSize,
-    CrossAxisAlignment? crossAxisAlignment,
-    TextDirection? textDirection,
-    VerticalDirection? verticalDirection,
-    TextBaseline? textBaseline,
-  }) {
-    return FlexLayoutProperties(
-      size: size ?? this.size,
-      children: children ?? this.children,
-      node: node,
-      constraints: constraints ?? this.constraints,
-      isFlex: isFlex ?? this.isFlex,
-      description: description ?? this.description,
-      flexFactor: flexFactor ?? this.flexFactor,
-      flexFit: flexFit ?? this.flexFit,
-      direction: direction ?? this.direction,
-      mainAxisAlignment: mainAxisAlignment ?? this.mainAxisAlignment,
-      mainAxisSize: mainAxisSize ?? this.mainAxisSize,
-      crossAxisAlignment: crossAxisAlignment ?? this.crossAxisAlignment,
-      textDirection: textDirection ?? this.textDirection,
-      verticalDirection: verticalDirection ?? this.verticalDirection,
-      textBaseline: textBaseline ?? this.textBaseline,
-    );
-  }
-
-  static FlexLayoutProperties _buildNode(RemoteDiagnosticsNode node) {
-    final renderObjectJson = node.renderObject!.json;
-    final properties = (renderObjectJson['properties'] as List<Object?>)
-        .cast<Map<String, Object?>>();
-
-    final data = {
-      for (final property in properties)
-        property['name']: property['description'] as String?,
-    };
-
-    return FlexLayoutProperties._fromNode(
-      node,
-      direction: _directionNamesToValues[data['direction']] ?? Axis.vertical,
-      mainAxisAlignment:
-          _mainAxisAlignmentNamesToValues[data['mainAxisAlignment']],
-      mainAxisSize: _mainAxisSizeNamesToValues[data['mainAxisSize']],
-      crossAxisAlignment:
-          _crossAxisAlignmentNamesToValues[data['crossAxisAlignment']],
-      textDirection:
-          _textDirectionNamesToValues[data['textDirection']] ??
-          TextDirection.ltr,
-      verticalDirection:
-          _verticalDirectionNamesToValues[data['verticalDirection']] ??
-          VerticalDirection.down,
-      textBaseline: _textBaselineNamesToValues[data['textBaseline']],
-    );
-  }
-
-  final Axis direction;
-  final MainAxisAlignment? mainAxisAlignment;
-  final CrossAxisAlignment? crossAxisAlignment;
-  final MainAxisSize? mainAxisSize;
-  final TextDirection textDirection;
-  final VerticalDirection verticalDirection;
-  final TextBaseline? textBaseline;
-
-  List<LayoutProperties>? _displayChildren;
-
-  @override
-  List<LayoutProperties> get displayChildren {
-    final displayChildren = _displayChildren;
-    if (displayChildren != null) return displayChildren;
-    return _displayChildren = startIsTopLeft
-        ? children
-        : children.reversed.toList();
-  }
-
-  int? _totalFlex;
-
-  bool get isMainAxisHorizontal => direction == Axis.horizontal;
-
-  bool get isMainAxisVertical => direction == Axis.vertical;
-
-  String get horizontalDirectionDescription {
-    return direction == Axis.horizontal ? 'Main Axis' : 'Cross Axis';
-  }
-
-  String get verticalDirectionDescription {
-    return direction == Axis.vertical ? 'Main Axis' : 'Cross Axis';
-  }
-
-  String get type => direction.flexType;
-
-  num get totalFlex {
-    if (children.isEmpty) return 0;
-    _totalFlex ??= children
-        .map((child) => child.flexFactor ?? 0)
-        .reduce((value, element) => value + element)
-        .toInt();
-    return _totalFlex!;
-  }
-
-  Axis get crossAxisDirection {
-    return direction == Axis.horizontal ? Axis.vertical : Axis.horizontal;
-  }
-
-  double get mainAxisDimension => dimension(direction);
-
-  double get crossAxisDimension => dimension(crossAxisDirection);
-
-  @override
-  bool get isOverflowWidth {
-    if (direction == Axis.horizontal) {
-      return width + overflowEpsilon < sum(childrenWidths);
-    }
-    return width + overflowEpsilon < max(childrenWidths);
-  }
-
-  @override
-  bool get isOverflowHeight {
-    if (direction == Axis.vertical) {
-      return height + overflowEpsilon < sum(childrenHeights);
-    }
-    return height + overflowEpsilon < max(childrenHeights);
-  }
-
-  bool get startIsTopLeft {
-    switch (direction) {
-      case Axis.horizontal:
-        switch (textDirection) {
-          case TextDirection.ltr:
-            return true;
-          case TextDirection.rtl:
-            return false;
-        }
-      case Axis.vertical:
-        switch (verticalDirection) {
-          case VerticalDirection.down:
-            return true;
-          case VerticalDirection.up:
-            return false;
-        }
-    }
-  }
-
-  /// render properties for laying out rendered Flex & Flex children widgets
-  /// the computation is similar to [RenderFlex].performLayout() method
-  List<RenderProperties> childrenRenderProperties({
-    required double smallestRenderWidth,
-    required double largestRenderWidth,
-    required double smallestRenderHeight,
-    required double largestRenderHeight,
-    required double Function(Axis) maxSizeAvailable,
-  }) {
-    /// calculate the render empty spaces
-    final freeSpace = dimension(direction) - sum(childrenDimensions(direction));
-    final displayMainAxisAlignment = startIsTopLeft
-        ? mainAxisAlignment
-        : mainAxisAlignment?.reversed;
-
-    double leadingSpace(double freeSpace) {
-      if (children.isEmpty) return 0.0;
-      switch (displayMainAxisAlignment) {
-        case MainAxisAlignment.start:
-        case MainAxisAlignment.end:
-          return freeSpace;
-        case MainAxisAlignment.center:
-          return freeSpace * 0.5;
-        case MainAxisAlignment.spaceBetween:
-          return 0.0;
-        case MainAxisAlignment.spaceAround:
-          final spaceBetweenChildren = freeSpace / children.length;
-          return spaceBetweenChildren * 0.5;
-        case MainAxisAlignment.spaceEvenly:
-          return freeSpace / (children.length + 1);
-        default:
-          return 0.0;
-      }
-    }
-
-    double betweenSpace(double freeSpace) {
-      if (children.isEmpty) return 0.0;
-      switch (displayMainAxisAlignment) {
-        case MainAxisAlignment.start:
-        case MainAxisAlignment.end:
-        case MainAxisAlignment.center:
-          return 0.0;
-        case MainAxisAlignment.spaceBetween:
-          if (children.length == 1) return freeSpace;
-          return freeSpace / (children.length - 1);
-        case MainAxisAlignment.spaceAround:
-          return freeSpace / children.length;
-        case MainAxisAlignment.spaceEvenly:
-          return freeSpace / (children.length + 1);
-        default:
-          return 0.0;
-      }
-    }
-
-    double smallestRenderSize(Axis axis) {
-      return axis == Axis.horizontal
-          ? smallestRenderWidth
-          : smallestRenderHeight;
-    }
-
-    double largestRenderSize(Axis axis) {
-      final lrs = axis == Axis.horizontal
-          ? largestRenderWidth
-          : largestRenderHeight;
-      // use all the space when visualizing cross axis
-      return (axis == direction) ? lrs : maxSizeAvailable(axis);
-    }
-
-    List<double> renderSizes(Axis axis) {
-      final sizes = childrenDimensions(axis);
-      if (freeSpace > 0.0 && axis == direction) {
-        /// include free space in the computation
-        sizes.add(freeSpace);
-      }
-      final smallestSize = min(sizes);
-      final largestSize = max(sizes);
-      if (axis == direction ||
-          (crossAxisAlignment != CrossAxisAlignment.stretch &&
-              smallestSize != largestSize)) {
-        return computeRenderSizes(
-          sizes: sizes,
-          smallestSize: smallestSize,
-          largestSize: largestSize,
-          smallestRenderSize: smallestRenderSize(axis),
-          largestRenderSize: largestRenderSize(axis),
-          maxSizeAvailable: maxSizeAvailable(axis),
-        );
-      } else {
-        // uniform cross axis sizes.
-        double size = crossAxisAlignment == CrossAxisAlignment.stretch
-            ? maxSizeAvailable(axis)
-            : largestSize /
-                  math.max(dimension(axis), 1.0) *
-                  maxSizeAvailable(axis);
-        size = math.max(size, smallestRenderSize(axis));
-        return sizes.map((_) => size).toList();
-      }
-    }
-
-    final widths = renderSizes(Axis.horizontal);
-    final heights = renderSizes(Axis.vertical);
-
-    final renderFreeSpace = freeSpace > 0.0
-        ? (isMainAxisHorizontal ? widths.last : heights.last)
-        : 0.0;
-
-    final renderLeadingSpace = leadingSpace(renderFreeSpace);
-    final renderBetweenSpace = betweenSpace(renderFreeSpace);
-
-    final childrenRenderProps = <RenderProperties>[];
-
-    double lastMainAxisOffset() {
-      if (childrenRenderProps.isEmpty) return 0.0;
-      return childrenRenderProps.last.mainAxisOffset;
-    }
-
-    double lastMainAxisDimension() {
-      if (childrenRenderProps.isEmpty) return 0.0;
-      return childrenRenderProps.last.mainAxisDimension;
-    }
-
-    double space(int index) {
-      if (index == 0) {
-        if (displayMainAxisAlignment == MainAxisAlignment.start) return 0.0;
-        return renderLeadingSpace;
-      }
-      return renderBetweenSpace;
-    }
-
-    double calculateMainAxisOffset(int i) {
-      return lastMainAxisOffset() + lastMainAxisDimension() + space(i);
-    }
-
-    double calculateCrossAxisOffset(int i) {
-      final maxDimension = maxSizeAvailable(crossAxisDirection);
-      final usedDimension = crossAxisDirection == Axis.horizontal
-          ? widths[i]
-          : heights[i];
-
-      if (crossAxisAlignment == CrossAxisAlignment.start ||
-          crossAxisAlignment == CrossAxisAlignment.stretch ||
-          maxDimension == usedDimension) {
-        return 0.0;
-      }
-      final emptySpace = math.max(0.0, maxDimension - usedDimension);
-      if (crossAxisAlignment == CrossAxisAlignment.end) return emptySpace;
-      return emptySpace * 0.5;
-    }
-
-    for (var i = 0; i < children.length; ++i) {
-      childrenRenderProps.add(
-        RenderProperties(
-            axis: direction,
-            size: Size(widths[i], heights[i]),
-            offset: Offset.zero,
-            realSize: displayChildren[i].size,
-            layoutProperties: displayChildren[i],
-          )
-          ..mainAxisOffset = calculateMainAxisOffset(i)
-          ..crossAxisOffset = calculateCrossAxisOffset(i),
-      );
-    }
-
-    final spaces = <RenderProperties>[];
-    final actualLeadingSpace = leadingSpace(freeSpace);
-    final actualBetweenSpace = betweenSpace(freeSpace);
-    final renderPropsWithFullCrossAxisDimension =
-        RenderProperties(
-            axis: direction,
-            isFreeSpace: true,
-            layoutProperties: this,
-          )
-          ..crossAxisDimension = maxSizeAvailable(crossAxisDirection)
-          ..crossAxisRealDimension = dimension(crossAxisDirection)
-          ..crossAxisOffset = 0.0;
-    if (actualLeadingSpace > 0.0 &&
-        displayMainAxisAlignment != MainAxisAlignment.start) {
-      spaces.add(
-        renderPropsWithFullCrossAxisDimension.copyWith()
-          ..mainAxisOffset = 0.0
-          ..mainAxisDimension = renderLeadingSpace
-          ..mainAxisRealDimension = actualLeadingSpace,
-      );
-    }
-    if (actualBetweenSpace > 0.0) {
-      for (var i = 0; i < childrenRenderProps.length - 1; ++i) {
-        final child = childrenRenderProps[i];
-        spaces.add(
-          renderPropsWithFullCrossAxisDimension.copyWith()
-            ..mainAxisDimension = renderBetweenSpace
-            ..mainAxisRealDimension = actualBetweenSpace
-            ..mainAxisOffset = child.mainAxisOffset + child.mainAxisDimension,
-        );
-      }
-    }
-    if (actualLeadingSpace > 0.0 &&
-        displayMainAxisAlignment != MainAxisAlignment.end) {
-      spaces.add(
-        renderPropsWithFullCrossAxisDimension.copyWith()
-          ..mainAxisOffset =
-              childrenRenderProps.last.mainAxisDimension +
-              childrenRenderProps.last.mainAxisOffset
-          ..mainAxisDimension = renderLeadingSpace
-          ..mainAxisRealDimension = actualLeadingSpace,
-      );
-    }
-    return [...childrenRenderProps, ...spaces];
-  }
-
-  List<RenderProperties> crossAxisSpaces({
-    required List<RenderProperties> childrenRenderProperties,
-    required double Function(Axis) maxSizeAvailable,
-  }) {
-    if (crossAxisAlignment == CrossAxisAlignment.stretch) return [];
-    final spaces = <RenderProperties>[];
-    for (var i = 0; i < children.length; ++i) {
-      if (dimension(crossAxisDirection) ==
-              displayChildren[i].dimension(crossAxisDirection) ||
-          childrenRenderProperties[i].crossAxisDimension ==
-              maxSizeAvailable(crossAxisDirection)) {
-        continue;
-      }
-
-      final renderProperties = childrenRenderProperties[i];
-      final space = renderProperties.copyWith(isFreeSpace: true);
-
-      space.crossAxisRealDimension =
-          crossAxisDimension - space.crossAxisRealDimension;
-      space.crossAxisDimension =
-          maxSizeAvailable(crossAxisDirection) - space.crossAxisDimension;
-      if (space.crossAxisDimension <= 0.0) continue;
-      if (crossAxisAlignment == CrossAxisAlignment.center) {
-        space.crossAxisDimension *= 0.5;
-        final crossAxisRealDimension = space.crossAxisRealDimension;
-        space.crossAxisRealDimension = crossAxisRealDimension * 0.5;
-        spaces.add(space.copyWith()..crossAxisOffset = 0.0);
-        spaces.add(
-          space.copyWith()
-            ..crossAxisOffset =
-                renderProperties.crossAxisDimension +
-                renderProperties.crossAxisOffset,
-        );
-      } else {
-        space.crossAxisOffset = crossAxisAlignment == CrossAxisAlignment.end
-            ? 0
-            : renderProperties.crossAxisDimension;
-        spaces.add(space);
-      }
-    }
-    return spaces;
-  }
-
-  static final _directionNamesToValues = Axis.values.asNameMap();
-  static final _mainAxisAlignmentNamesToValues = MainAxisAlignment.values
-      .asNameMap();
-  static final _mainAxisSizeNamesToValues = MainAxisSize.values.asNameMap();
-  static final _crossAxisAlignmentNamesToValues = CrossAxisAlignment.values
-      .asNameMap();
-  static final _textDirectionNamesToValues = TextDirection.values.asNameMap();
-  static final _verticalDirectionNamesToValues = VerticalDirection.values
-      .asNameMap();
-  static final _textBaselineNamesToValues = TextBaseline.values.asNameMap();
-}
-
-/// Information for rendering a [LayoutProperties] node.
-class RenderProperties {
-  RenderProperties({
-    required this.axis,
-    required this.layoutProperties,
-    this.isFreeSpace = false,
-    Size? size,
-    Offset? offset,
-    Size? realSize,
-  }) : width = size?.width ?? 0.0,
-       height = size?.height ?? 0.0,
-       realWidth = realSize?.width ?? 0.0,
-       realHeight = realSize?.height ?? 0.0,
-       dx = offset?.dx ?? 0.0,
-       dy = offset?.dy ?? 0.0;
-
-  final Axis axis;
-
-  /// Represents which node is rendered for this object.
-  final LayoutProperties layoutProperties;
-
-  final bool isFreeSpace;
-
-  double dx, dy;
-  double width, height;
-  double realWidth, realHeight;
-
-  Size get size => Size(width, height);
-
-  Size get realSize => Size(realWidth, realHeight);
-
-  Offset get offset => Offset(dx, dy);
-
-  double get mainAxisDimension => axis == Axis.horizontal ? width : height;
-
-  set mainAxisDimension(double dim) {
-    if (axis == Axis.horizontal) {
-      width = dim;
-    } else {
-      height = dim;
-    }
-  }
-
-  double get crossAxisDimension => axis == Axis.horizontal ? height : width;
-
-  set crossAxisDimension(double dim) {
-    if (axis == Axis.horizontal) {
-      height = dim;
-    } else {
-      width = dim;
-    }
-  }
-
-  double get mainAxisOffset => axis == Axis.horizontal ? dx : dy;
-
-  set mainAxisOffset(double offset) {
-    if (axis == Axis.horizontal) {
-      dx = offset;
-    } else {
-      dy = offset;
-    }
-  }
-
-  double get crossAxisOffset => axis == Axis.horizontal ? dy : dx;
-
-  set crossAxisOffset(double offset) {
-    if (axis == Axis.horizontal) {
-      dy = offset;
-    } else {
-      dx = offset;
-    }
-  }
-
-  double get mainAxisRealDimension =>
-      axis == Axis.horizontal ? realWidth : realHeight;
-
-  set mainAxisRealDimension(double newVal) {
-    if (axis == Axis.horizontal) {
-      realWidth = newVal;
-    } else {
-      realHeight = newVal;
-    }
-  }
-
-  double get crossAxisRealDimension =>
-      axis == Axis.horizontal ? realHeight : realWidth;
-
-  set crossAxisRealDimension(double newVal) {
-    if (axis == Axis.horizontal) {
-      realHeight = newVal;
-    } else {
-      realWidth = newVal;
-    }
-  }
-
-  RenderProperties copyWith({bool? isFreeSpace}) {
-    return RenderProperties(
-      axis: axis,
-      size: size,
-      offset: offset,
-      realSize: realSize,
-      layoutProperties: layoutProperties,
-      isFreeSpace: isFreeSpace ?? this.isFreeSpace,
-    );
-  }
-
-  @override
-  int get hashCode =>
-      axis.hashCode ^
-      size.hashCode ^
-      offset.hashCode ^
-      realSize.hashCode ^
-      isFreeSpace.hashCode;
-
-  @override
-  bool operator ==(Object other) {
-    return other is RenderProperties &&
-        axis == other.axis &&
-        size.closeTo(other.size) &&
-        offset.closeTo(other.offset) &&
-        realSize.closeTo(other.realSize) &&
-        isFreeSpace == other.isFreeSpace;
-  }
-
-  @override
-  String toString() {
-    return '{ axis: $axis, size: $size, offset: $offset, realSize: $realSize, isFreeSpace: $isFreeSpace }';
-  }
-}
-
-bool _closeTo(double a, double b, {int precision = 1}) {
-  return a.toStringAsPrecision(precision) == b.toStringAsPrecision(precision);
-}
-
-extension on Size {
-  bool closeTo(Size other) {
-    return _closeTo(width, other.width) && _closeTo(height, other.height);
-  }
-}
-
-extension on Offset {
-  bool closeTo(Offset other) {
-    return _closeTo(dx, other.dx) && _closeTo(dy, other.dy);
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart
deleted file mode 100644
index 5ab577d..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart
+++ /dev/null
@@ -1,458 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/material.dart';
-
-import '../../service/service_extension_widgets.dart';
-import '../../service/service_extensions.dart' as extensions;
-import '../../shared/analytics/analytics.dart' as ga;
-import '../../shared/analytics/constants.dart' as gac;
-import '../../shared/analytics/metrics.dart';
-import '../../shared/console/eval/inspector_tree.dart';
-import '../../shared/globals.dart';
-import '../../shared/managers/banner_messages.dart';
-import '../../shared/managers/error_badge_manager.dart';
-import '../../shared/primitives/blocking_action_mixin.dart';
-import '../../shared/ui/common_widgets.dart';
-import '../../shared/ui/search.dart';
-import '../inspector_shared/inspector_controls.dart';
-import '../inspector_shared/inspector_screen.dart';
-import '../inspector_shared/inspector_settings_dialog.dart';
-import 'inspector_controller.dart';
-import 'inspector_screen_details_tab.dart';
-import 'inspector_tree_controller.dart';
-
-class InspectorScreenBody extends StatefulWidget {
-  const InspectorScreenBody({super.key, required this.controller});
-
-  final InspectorController controller;
-
-  @override
-  InspectorScreenBodyState createState() => InspectorScreenBodyState();
-}
-
-class InspectorScreenBodyState extends State<InspectorScreenBody>
-    with BlockingActionMixin, AutoDisposeMixin {
-  InspectorController get controller => widget.controller;
-
-  InspectorTreeController get _summaryTreeController =>
-      controller.inspectorTree;
-
-  InspectorTreeController get _detailsTreeController =>
-      controller.details!.inspectorTree;
-
-  bool searchVisible = false;
-
-  SearchControllerMixin get searchController => _summaryTreeController;
-
-  /// Indicates whether search can be closed. The value is set to true when
-  /// search target type dropdown is displayed
-  /// TODO(https://github.com/flutter/devtools/issues/3489) use this variable when adding the scope dropdown
-  bool searchPreventClose = false;
-
-  SearchTargetType searchTarget = SearchTargetType.widget;
-
-  static const summaryTreeKey = Key('Summary Tree');
-  static const detailsTreeKey = Key('Details Tree');
-  static const minScreenWidthForText = 900.0;
-  static const serviceExtensionButtonsIncludeTextWidth = 1200.0;
-
-  @override
-  void initState() {
-    super.initState();
-    ga.screen(InspectorScreen.id);
-  }
-
-  @override
-  void didChangeDependencies() {
-    super.didChangeDependencies();
-
-    if (serviceConnection.inspectorService == null) {
-      // The app must not be a Flutter app.
-      return;
-    }
-
-    cancelListeners();
-    searchVisible = searchController.search.isNotEmpty;
-    addAutoDisposeListener(searchController.searchFieldFocusNode, () {
-      final searchFieldFocusNode = searchController.searchFieldFocusNode;
-      if (searchFieldFocusNode == null) return;
-      // Close the search once focus is lost and following conditions are met:
-      //  1. Search string is empty.
-      //  2. [searchPreventClose] == false (this is set true when searchTargetType Dropdown is opened).
-      if (!searchFieldFocusNode.hasFocus &&
-          searchController.search.isEmpty &&
-          !searchPreventClose) {
-        setState(() {
-          searchVisible = false;
-        });
-      }
-
-      // Reset [searchPreventClose] state to false after the search field gains focus.
-      // Focus is returned automatically once the Dropdown menu is closed.
-      if (searchFieldFocusNode.hasFocus) {
-        searchPreventClose = false;
-      }
-    });
-    addAutoDisposeListener(preferences.inspector.pubRootDirectories, () {
-      if (serviceConnection.serviceManager.connectedState.value.connected &&
-          controller.firstInspectorTreeLoadCompleted) {
-        _refreshInspector();
-      }
-    });
-
-    if (!controller.firstInspectorTreeLoadCompleted) {
-      ga.timeStart(InspectorScreen.id, gac.pageReady);
-    }
-
-    _summaryTreeController.setSearchTarget(searchTarget);
-
-    _showLegacyInspectorWarning(context);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final summaryTree = _buildSummaryTreeColumn();
-
-    final detailsTree = InspectorTree(
-      key: detailsTreeKey,
-      controller: controller,
-      treeController: _detailsTreeController,
-      summaryTreeController: _summaryTreeController,
-      screenId: InspectorScreen.id,
-    );
-
-    final splitAxis = SplitPane.axisFor(context, 0.85);
-    final widgetTrees = SplitPane(
-      axis: splitAxis,
-      initialFractions: const [0.33, 0.67],
-      children: [
-        summaryTree,
-        InspectorDetails(detailsTree: detailsTree, controller: controller),
-      ],
-    );
-    return Column(
-      children: <Widget>[
-        const InspectorControls(),
-        const SizedBox(height: intermediateSpacing),
-        Expanded(child: widgetTrees),
-      ],
-    );
-  }
-
-  Widget _buildSummaryTreeColumn() {
-    return LayoutBuilder(
-      builder: (context, constraints) {
-        return RoundedOutlinedBorder(
-          child: Column(
-            children: [
-              InspectorSummaryTreeControls(
-                isSearchVisible: searchVisible,
-                constraints: constraints,
-                onRefreshInspectorPressed: _refreshInspector,
-                onSearchVisibleToggle: _onSearchVisibleToggle,
-                searchFieldBuilder: () =>
-                    StatelessSearchField<InspectorTreeRow>(
-                      controller: _summaryTreeController,
-                      searchFieldEnabled: true,
-                      shouldRequestFocus: searchVisible,
-                      supportsNavigation: true,
-                      onClose: _onSearchVisibleToggle,
-                    ),
-              ),
-              Expanded(
-                child: ValueListenableBuilder(
-                  valueListenable: serviceConnection.errorBadgeManager
-                      .erroredItemsForPage(InspectorScreen.id),
-                  builder: (_, LinkedHashMap<String, DevToolsError> errors, _) {
-                    final inspectableErrors =
-                        errors.map(
-                              (key, value) => MapEntry(
-                                key,
-                                value as InspectableWidgetError,
-                              ),
-                            )
-                            as LinkedHashMap<String, InspectableWidgetError>;
-                    return Stack(
-                      children: [
-                        InspectorTree(
-                          key: summaryTreeKey,
-                          controller: controller,
-                          treeController: _summaryTreeController,
-                          isSummaryTree: true,
-                          widgetErrors: inspectableErrors,
-                          screenId: InspectorScreen.id,
-                        ),
-                        if (errors.isNotEmpty)
-                          ValueListenableBuilder<int?>(
-                            valueListenable: controller.selectedErrorIndex,
-                            builder: (_, selectedErrorIndex, _) => Positioned(
-                              top: 0,
-                              right: 0,
-                              child: ErrorNavigator(
-                                errors: inspectableErrors,
-                                errorIndex: selectedErrorIndex,
-                                onSelectError: controller.selectErrorByIndex,
-                              ),
-                            ),
-                          ),
-                      ],
-                    );
-                  },
-                ),
-              ),
-            ],
-          ),
-        );
-      },
-    );
-  }
-
-  void _onSearchVisibleToggle() {
-    setState(() {
-      searchVisible = !searchVisible;
-    });
-    _summaryTreeController.resetSearch();
-  }
-
-  void _showLegacyInspectorWarning(BuildContext context) {
-    if (context.mounted) {
-      pushLegacyInspectorWarning(InspectorScreen.id);
-    }
-  }
-
-  List<Widget> getServiceExtensionWidgets() {
-    return [
-      ServiceExtensionButtonGroup(
-        minScreenWidthForText: serviceExtensionButtonsIncludeTextWidth,
-        extensions: [
-          extensions.slowAnimations,
-          extensions.debugPaint,
-          extensions.debugPaintBaselines,
-          extensions.repaintRainbow,
-          extensions.invertOversizedImages,
-        ],
-      ),
-      const SizedBox(width: defaultSpacing),
-      SettingsOutlinedButton(
-        gaScreen: gac.inspector,
-        gaSelection: gac.inspectorSettings,
-        tooltip: 'Flutter Inspector Settings',
-        onPressed: () {
-          unawaited(
-            showDialog(
-              context: context,
-              builder: (context) => const FlutterInspectorSettingsDialog(),
-            ),
-          );
-        },
-      ),
-      // TODO(jacobr): implement TogglePlatformSelector.
-      //  TogglePlatformSelector().selector
-    ];
-  }
-
-  void _refreshInspector() {
-    ga.select(
-      gac.inspector,
-      gac.refresh,
-      screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
-    );
-    unawaited(
-      blockWhileInProgress(() async {
-        // If the user is force refreshing the inspector before the first load has
-        // completed, this could indicate a slow load time or that the inspector
-        // failed to load the tree once available.
-        if (!controller.firstInspectorTreeLoadCompleted) {
-          // We do not want to complete this timing operation because the force
-          // refresh will skew the results.
-          ga.cancelTimingOperation(InspectorScreen.id, gac.pageReady);
-          ga.select(
-            gac.inspector,
-            gac.refreshEmptyTree,
-            screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
-          );
-          controller.firstInspectorTreeLoadCompleted = true;
-        }
-        await controller.onForceRefresh();
-      }),
-    );
-  }
-}
-
-class InspectorSummaryTreeControls extends StatelessWidget {
-  const InspectorSummaryTreeControls({
-    super.key,
-    required this.constraints,
-    required this.isSearchVisible,
-    required this.onRefreshInspectorPressed,
-    required this.onSearchVisibleToggle,
-    required this.searchFieldBuilder,
-  });
-
-  static const _searchBreakpoint = 375.0;
-
-  final bool isSearchVisible;
-  final BoxConstraints constraints;
-  final VoidCallback onRefreshInspectorPressed;
-  final VoidCallback onSearchVisibleToggle;
-  final Widget Function() searchFieldBuilder;
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(
-      children: [
-        _controlsContainer(
-          context,
-          Row(
-            children: <Widget>[
-              Padding(
-                padding: const EdgeInsets.symmetric(horizontal: denseSpacing),
-                child: Text(
-                  'Widget Tree',
-                  style: Theme.of(context).textTheme.titleMedium,
-                ),
-              ),
-              ...!isSearchVisible
-                  ? [
-                      const Spacer(),
-                      ToolbarAction(
-                        icon: Icons.search,
-                        onPressed: onSearchVisibleToggle,
-                        tooltip: 'Search Tree',
-                      ),
-                    ]
-                  : [
-                      constraints.maxWidth >= _searchBreakpoint
-                          ? _buildSearchControls()
-                          : const Spacer(),
-                    ],
-              ToolbarAction(
-                icon: Icons.refresh,
-                onPressed: onRefreshInspectorPressed,
-                tooltip: 'Refresh Tree',
-              ),
-            ],
-          ),
-        ),
-        if (isSearchVisible && constraints.maxWidth < _searchBreakpoint)
-          _controlsContainer(context, Row(children: [_buildSearchControls()])),
-      ],
-    );
-  }
-
-  Container _controlsContainer(BuildContext context, Widget child) {
-    return Container(
-      height: defaultHeaderHeight,
-      decoration: BoxDecoration(
-        border: Border(bottom: defaultBorderSide(Theme.of(context))),
-      ),
-      child: child,
-    );
-  }
-
-  Widget _buildSearchControls() {
-    return Expanded(
-      child: SizedBox(
-        height: defaultTextFieldHeight,
-        child: searchFieldBuilder(),
-      ),
-    );
-  }
-}
-
-class ErrorNavigator extends StatelessWidget {
-  const ErrorNavigator({
-    super.key,
-    required this.errors,
-    required this.errorIndex,
-    required this.onSelectError,
-  });
-
-  final LinkedHashMap<String, InspectableWidgetError> errors;
-
-  final int? errorIndex;
-
-  final void Function(int) onSelectError;
-
-  @override
-  Widget build(BuildContext context) {
-    final colorScheme = Theme.of(context).colorScheme;
-    final label = errorIndex != null
-        ? 'Error ${errorIndex! + 1}/${errors.length}'
-        : 'Errors: ${errors.length}';
-    return Container(
-      color: colorScheme.errorContainer,
-      child: Padding(
-        padding: const EdgeInsets.symmetric(
-          horizontal: defaultSpacing,
-          vertical: denseSpacing,
-        ),
-        child: Row(
-          children: [
-            Padding(
-              padding: const EdgeInsets.only(right: denseSpacing),
-              child: Text(
-                label,
-                style: TextStyle(color: colorScheme.onErrorContainer),
-              ),
-            ),
-            _ErrorNavigatorButton(
-              icon: Icons.keyboard_arrow_up,
-              onPressed: _previousError,
-            ),
-            _ErrorNavigatorButton(
-              icon: Icons.keyboard_arrow_down,
-              onPressed: _nextError,
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-
-  void _previousError() {
-    var newIndex = errorIndex == null ? errors.length - 1 : errorIndex! - 1;
-    while (newIndex < 0) {
-      newIndex += errors.length;
-    }
-
-    onSelectError(newIndex);
-  }
-
-  void _nextError() {
-    final newIndex = errorIndex == null ? 0 : (errorIndex! + 1) % errors.length;
-
-    onSelectError(newIndex);
-  }
-}
-
-class _ErrorNavigatorButton extends StatelessWidget {
-  const _ErrorNavigatorButton({required this.icon, required this.onPressed});
-
-  final IconData icon;
-  final VoidCallback onPressed;
-
-  @override
-  Widget build(BuildContext context) {
-    return SizedBox(
-      // This is required to force the button size.
-      height: defaultButtonHeight,
-      width: defaultButtonHeight,
-      child: IconButton(
-        padding: EdgeInsets.zero,
-        constraints: const BoxConstraints(),
-        splashRadius: defaultIconSize,
-        icon: Icon(icon),
-        color: Theme.of(context).colorScheme.onErrorContainer,
-        onPressed: onPressed,
-      ),
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart
deleted file mode 100644
index ae8cc53..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_details_tab.dart
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../shared/analytics/analytics.dart' as ga;
-import '../../shared/analytics/constants.dart' as gac;
-import '../../shared/globals.dart';
-import '../../shared/preferences/preferences.dart';
-import '../../shared/primitives/blocking_action_mixin.dart';
-import '../../shared/ui/common_widgets.dart';
-import '../../shared/ui/tab.dart';
-import 'inspector_controller.dart';
-import 'inspector_screen_body.dart';
-import 'layout_explorer/layout_explorer.dart';
-
-class InspectorDetails extends StatelessWidget {
-  const InspectorDetails({
-    required this.detailsTree,
-    required this.controller,
-    super.key,
-  });
-
-  final Widget detailsTree;
-  final InspectorController controller;
-
-  @override
-  Widget build(BuildContext context) {
-    final tabs = [
-      (
-        tab: _buildTab(tabName: InspectorDetailsViewType.layoutExplorer.key),
-        tabView: LayoutExplorerTab(controller: controller),
-      ),
-      (
-        tab: _buildTab(
-          tabName: InspectorDetailsViewType.widgetDetailsTree.key,
-          trailing: InspectorExpandCollapseButtons(controller: controller),
-        ),
-        tabView: detailsTree,
-      ),
-    ];
-    return ValueListenableBuilder(
-      valueListenable: preferences.inspector.defaultDetailsView,
-      builder: (BuildContext context, value, Widget? child) {
-        int defaultInspectorViewIndex = 0;
-
-        if (preferences.inspector.defaultDetailsView.value ==
-            InspectorDetailsViewType.widgetDetailsTree) {
-          defaultInspectorViewIndex = 1;
-        }
-
-        return AnalyticsTabbedView(
-          tabs: tabs,
-          gaScreen: gac.inspector,
-          initialSelectedIndex: defaultInspectorViewIndex,
-        );
-      },
-    );
-  }
-
-  DevToolsTab _buildTab({required String tabName, Widget? trailing}) {
-    return DevToolsTab.create(
-      tabName: tabName,
-      gaPrefix: 'inspectorDetailsTab',
-      trailing: trailing,
-    );
-  }
-}
-
-class InspectorExpandCollapseButtons extends StatefulWidget {
-  const InspectorExpandCollapseButtons({super.key, required this.controller});
-
-  final InspectorController controller;
-
-  @override
-  State<InspectorExpandCollapseButtons> createState() =>
-      _InspectorExpandCollapseButtonsState();
-}
-
-class _InspectorExpandCollapseButtonsState
-    extends State<InspectorExpandCollapseButtons>
-    with BlockingActionMixin {
-  bool get enableButtons => !actionInProgress;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      alignment: Alignment.centerRight,
-      decoration: BoxDecoration(
-        border: Border(left: defaultBorderSide(Theme.of(context))),
-      ),
-      child: Row(
-        mainAxisAlignment: MainAxisAlignment.end,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          SizedBox(
-            child: GaDevToolsButton(
-              icon: Icons.unfold_more,
-              onPressed: enableButtons ? _onExpandClick : null,
-              label: 'Expand all',
-              minScreenWidthForText:
-                  InspectorScreenBodyState.minScreenWidthForText,
-              gaScreen: gac.inspector,
-              gaSelection: gac.expandAll,
-              outlined: false,
-            ),
-          ),
-          const SizedBox(width: denseSpacing),
-          SizedBox(
-            child: GaDevToolsButton(
-              icon: Icons.unfold_less,
-              onPressed: enableButtons ? _onCollapseClick : null,
-              label: 'Collapse to selected',
-              minScreenWidthForText:
-                  InspectorScreenBodyState.minScreenWidthForText,
-              gaScreen: gac.inspector,
-              gaSelection: gac.collapseAll,
-              outlined: false,
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-
-  void _onExpandClick() {
-    unawaited(
-      blockWhileInProgress(() async {
-        ga.select(gac.inspector, gac.expandAll);
-        await widget.controller.expandAllNodesInDetailsTree();
-      }),
-    );
-  }
-
-  void _onCollapseClick() {
-    ga.select(gac.inspector, gac.collapseAll);
-    widget.controller.collapseDetailsToSelected();
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart
deleted file mode 100644
index 35b5d9b..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart
+++ /dev/null
@@ -1,1331 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-import 'dart:collection';
-import 'dart:math';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:logging/logging.dart';
-
-import '../../shared/analytics/analytics.dart' as ga;
-import '../../shared/analytics/constants.dart' as gac;
-import '../../shared/analytics/metrics.dart';
-import '../../shared/console/eval/inspector_tree.dart';
-import '../../shared/console/widgets/description.dart';
-import '../../shared/diagnostics/diagnostics_node.dart';
-import '../../shared/globals.dart';
-import '../../shared/managers/error_badge_manager.dart';
-import '../../shared/primitives/collapsible_mixin.dart';
-import '../../shared/primitives/diagnostics_text_styles.dart';
-import '../../shared/primitives/utils.dart';
-import '../../shared/ui/colors.dart';
-import '../../shared/ui/common_widgets.dart';
-import '../../shared/ui/search.dart';
-import '../../shared/ui/utils.dart';
-import '../../shared/utils/utils.dart';
-import 'inspector_breadcrumbs.dart';
-import 'inspector_controller.dart';
-
-final _log = Logger('inspector_tree_controller');
-
-/// Presents a [InspectorTreeNode].
-class _InspectorTreeRowWidget extends StatefulWidget {
-  /// Constructs a [_InspectorTreeRowWidget] that presents a line in the
-  /// Inspector tree.
-  const _InspectorTreeRowWidget({
-    required super.key,
-    required this.row,
-    required this.inspectorTreeState,
-    this.error,
-    required this.scrollControllerX,
-    required this.viewportWidth,
-  });
-
-  final _InspectorTreeState inspectorTreeState;
-
-  InspectorTreeNode get node => row.node;
-  final InspectorTreeRow row;
-  final ScrollController scrollControllerX;
-  final double viewportWidth;
-
-  /// A [DevToolsError] that applies to the widget in this row.
-  ///
-  /// This will be null if there is no error for this row.
-  final DevToolsError? error;
-
-  @override
-  _InspectorTreeRowState createState() => _InspectorTreeRowState();
-}
-
-class _InspectorTreeRowState extends State<_InspectorTreeRowWidget>
-    with TickerProviderStateMixin, CollapsibleAnimationMixin {
-  @override
-  Widget build(BuildContext context) {
-    return SizedBox(
-      height: inspectorRowHeight,
-      child: InspectorRowContent(
-        row: widget.row,
-        error: widget.error,
-        expandArrowAnimation: expandArrowAnimation,
-        controller: widget.inspectorTreeState.treeController!,
-        scrollControllerX: widget.scrollControllerX,
-        viewportWidth: widget.viewportWidth,
-        onToggle: () {
-          setExpanded(!isExpanded);
-        },
-      ),
-    );
-  }
-
-  @override
-  bool get isExpanded => widget.node.isExpanded;
-
-  @override
-  void onExpandChanged(bool expanded) {
-    setState(() {
-      final row = widget.row;
-      if (expanded) {
-        widget.inspectorTreeState.treeController!.onExpandRow(row);
-      } else {
-        widget.inspectorTreeState.treeController!.onCollapseRow(row);
-      }
-    });
-  }
-
-  @override
-  bool shouldShow() => widget.node.shouldShow;
-}
-
-class InspectorTreeController extends DisposableController
-    with SearchControllerMixin<InspectorTreeRow> {
-  InspectorTreeController({this.gaId}) {
-    init();
-  }
-
-  /// Clients the controller notifies to trigger changes to the UI.
-  final _clients = <InspectorControllerClient>{};
-
-  /// Identifier used when sending Google Analytics about events in this
-  /// [InspectorTreeController].
-  final int? gaId;
-
-  InspectorTreeNode createNode() => InspectorTreeNode();
-
-  SearchTargetType _searchTarget = SearchTargetType.widget;
-  int _rootSetCount = 0;
-
-  @override
-  void init() {
-    super.init();
-    ga.select(
-      gac.inspector,
-      gac.inspectorTreeControllerInitialized,
-      nonInteraction: true,
-      screenMetricsProvider: () => InspectorScreenMetrics.legacy(
-        inspectorTreeControllerId: gaId,
-        rootSetCount: _rootSetCount,
-        rowCount: _root?.subtreeSize,
-      ),
-    );
-  }
-
-  void addClient(InspectorControllerClient value) {
-    final firstClient = _clients.isEmpty;
-    _clients.add(value);
-    if (firstClient) {
-      config.onClientActiveChange?.call(true);
-    }
-  }
-
-  void removeClient(InspectorControllerClient value) {
-    _clients.remove(value);
-    if (_clients.isEmpty) {
-      config.onClientActiveChange?.call(false);
-    }
-  }
-
-  // Method defined to avoid a direct Flutter dependency.
-  void setState(VoidCallback fn) {
-    fn();
-    for (final client in _clients) {
-      client.onChanged();
-    }
-  }
-
-  void requestFocus() {
-    for (final client in _clients) {
-      client.requestFocus();
-    }
-  }
-
-  InspectorTreeNode? get root => _root;
-  InspectorTreeNode? _root;
-
-  set root(InspectorTreeNode? node) {
-    if (disposed) return;
-
-    setState(() {
-      _root = node;
-      _populateSearchableCachedRows();
-
-      ga.select(
-        gac.inspector,
-        gac.inspectorTreeControllerRootChange,
-        nonInteraction: true,
-        screenMetricsProvider: () => InspectorScreenMetrics.legacy(
-          inspectorTreeControllerId: gaId,
-          rootSetCount: ++_rootSetCount,
-          rowCount: _root?.subtreeSize,
-        ),
-      );
-    });
-  }
-
-  InspectorTreeNode? get selection => _selection;
-  InspectorTreeNode? _selection;
-
-  late final InspectorTreeConfig config;
-
-  set selection(InspectorTreeNode? node) {
-    if (node == _selection) return;
-
-    setState(() {
-      _selection?.selected = false;
-      _selection = node;
-      _selection?.selected = true;
-      final configLocal = config;
-      if (configLocal.onSelectionChange != null) {
-        configLocal.onSelectionChange!();
-      }
-    });
-  }
-
-  InspectorTreeNode? get hover => _hover;
-  InspectorTreeNode? _hover;
-
-  double? lastContentWidth;
-
-  final cachedRows = <InspectorTreeRow?>[];
-  InspectorTreeRow? _cachedSelectedRow;
-
-  /// All cached rows of the tree.
-  ///
-  /// Similar to [cachedRows] but:
-  /// * contains every row in the tree (including collapsed rows)
-  /// * items don't change when nodes are expanded or collapsed
-  /// * items are populated only when root is changed
-  final _searchableCachedRows = <InspectorTreeRow?>[];
-
-  void setSearchTarget(SearchTargetType searchTarget) {
-    _searchTarget = searchTarget;
-    refreshSearchMatches();
-  }
-
-  // TODO: we should add a listener instead that clears the cache when the
-  // root is marked as dirty.
-  void _maybeClearCache() {
-    final rootLocal = root;
-    if (rootLocal != null && rootLocal.isDirty) {
-      cachedRows.clear();
-      _cachedSelectedRow = null;
-      rootLocal.isDirty = false;
-      lastContentWidth = null;
-    }
-  }
-
-  void _populateSearchableCachedRows() {
-    _searchableCachedRows.clear();
-    for (int i = 0; i < numRows; i++) {
-      _searchableCachedRows.add(getCachedRow(i));
-    }
-  }
-
-  InspectorTreeRow? getCachedRow(int index) {
-    if (index < 0) return null;
-
-    _maybeClearCache();
-    while (cachedRows.length <= index) {
-      cachedRows.add(null);
-    }
-    cachedRows[index] ??= root?.getRow(index);
-
-    final cachedRow = cachedRows[index];
-    cachedRow?.isSearchMatch =
-        _searchableCachedRows.safeGet(index)?.isSearchMatch ?? false;
-
-    if (cachedRow?.isSelected == true) {
-      _cachedSelectedRow = cachedRow;
-    }
-    return cachedRow;
-  }
-
-  double getRowOffset(int index) {
-    return (getCachedRow(index)?.depth ?? 0) * inspectorColumnWidth;
-  }
-
-  List<InspectorTreeNode> getPathFromSelectedRowToRoot() {
-    final selectedItem = _cachedSelectedRow?.node;
-    if (selectedItem == null) return [];
-
-    final pathToRoot = <InspectorTreeNode>[selectedItem];
-    InspectorTreeNode? nextParentNode = selectedItem.parent;
-    while (nextParentNode != null) {
-      pathToRoot.add(nextParentNode);
-      nextParentNode = nextParentNode.parent;
-    }
-    return pathToRoot.reversed.toList();
-  }
-
-  set hover(InspectorTreeNode? node) {
-    if (node == _hover) {
-      return;
-    }
-    setState(() {
-      _hover = node;
-      // TODO(jacobr): we could choose to repaint only a portion of the UI
-    });
-  }
-
-  void navigateUp() {
-    _navigateHelper(-1);
-  }
-
-  void navigateDown() {
-    _navigateHelper(1);
-  }
-
-  void navigateLeft() {
-    final selectionLocal = selection;
-
-    // This logic is consistent with how IntelliJ handles tree navigation on
-    // on left arrow key press.
-    if (selectionLocal == null) {
-      _navigateHelper(-1);
-      return;
-    }
-
-    if (selectionLocal.isExpanded) {
-      setState(() {
-        selectionLocal.isExpanded = false;
-      });
-      return;
-    }
-    if (selectionLocal.parent != null) {
-      selection = selectionLocal.parent;
-    }
-  }
-
-  void navigateRight() {
-    // This logic is consistent with how IntelliJ handles tree navigation on
-    // on right arrow key press.
-
-    final selectionLocal = selection;
-
-    if (selectionLocal == null || selectionLocal.isExpanded) {
-      _navigateHelper(1);
-      return;
-    }
-
-    setState(() {
-      selectionLocal.isExpanded = true;
-    });
-  }
-
-  void _navigateHelper(int indexOffset) {
-    if (numRows == 0) return;
-
-    if (selection == null) {
-      selection = root;
-      return;
-    }
-
-    final rootLocal = root!;
-
-    selection = rootLocal
-        .getRow(
-          (rootLocal.getRowIndex(selection!) + indexOffset).clamp(
-            0,
-            numRows - 1,
-          ),
-        )
-        ?.node;
-  }
-
-  static const horizontalPadding = 10.0;
-
-  double getDepthIndent(int depth) {
-    return (depth + 1) * inspectorColumnWidth + horizontalPadding;
-  }
-
-  double rowYTop(int index) {
-    return inspectorRowHeight * index;
-  }
-
-  void nodeChanged(InspectorTreeNode node) {
-    setState(() {
-      node.isDirty = true;
-    });
-  }
-
-  void removeNodeFromParent(InspectorTreeNode node) {
-    setState(() {
-      node.parent?.removeChild(node);
-    });
-  }
-
-  void appendChild(InspectorTreeNode node, InspectorTreeNode child) {
-    setState(() {
-      node.appendChild(child);
-    });
-  }
-
-  void expandPath(InspectorTreeNode? node) {
-    setState(() {
-      _expandPath(node);
-    });
-  }
-
-  void _expandPath(InspectorTreeNode? node) {
-    while (node != null) {
-      if (!node.isExpanded) {
-        node.isExpanded = true;
-      }
-      node = node.parent;
-    }
-  }
-
-  void collapseToSelected() {
-    setState(() {
-      _collapseAllNodes(root!);
-      if (selection == null) return;
-      _expandPath(selection);
-    });
-  }
-
-  void _collapseAllNodes(InspectorTreeNode root) {
-    root.isExpanded = false;
-    root.children.forEach(_collapseAllNodes);
-  }
-
-  int get numRows => root?.subtreeSize ?? 0;
-
-  int getRowIndex(double y) => max(0, y ~/ inspectorRowHeight);
-
-  InspectorTreeRow? getRowForNode(InspectorTreeNode node) {
-    final rootLocal = root;
-    if (rootLocal == null) return null;
-    return getCachedRow(rootLocal.getRowIndex(node));
-  }
-
-  InspectorTreeRow? getRow(Offset offset) {
-    final rootLocal = root;
-    if (rootLocal == null) return null;
-    final row = getRowIndex(offset.dy);
-    return row < rootLocal.subtreeSize ? getCachedRow(row) : null;
-  }
-
-  void onExpandRow(InspectorTreeRow row) {
-    setState(() {
-      final onExpand = config.onExpand;
-      row.node.isExpanded = true;
-      if (onExpand != null) {
-        onExpand(row.node);
-      }
-    });
-  }
-
-  void onCollapseRow(InspectorTreeRow row) {
-    setState(() {
-      row.node.isExpanded = false;
-    });
-  }
-
-  void onSelectRow(InspectorTreeRow row) {
-    onSelectNode(row.node);
-  }
-
-  void onSelectNode(InspectorTreeNode? node) {
-    selection = node;
-    ga.select(
-      gac.inspector,
-      gac.treeNodeSelection,
-      screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
-    );
-    expandPath(node);
-  }
-
-  Rect getBoundingBox(InspectorTreeRow row) {
-    // For future reference: the bounding box likely needs to be in terms of
-    // positions after the current animations are complete so that computations
-    // to start animations to show specific widget scroll to where the target
-    // nodes will be displayed rather than where they are currently displayed.
-    final diagnostic = row.node.diagnostic;
-    // The node width is approximated since the widgets are not available at the
-    // time of calculating the bounding box.
-    final approximateNodeWidth =
-        DiagnosticsNodeDescription.approximateNodeWidth(diagnostic);
-    return Rect.fromLTWH(
-      getDepthIndent(row.depth),
-      rowYTop(row.index),
-      approximateNodeWidth,
-      inspectorRowHeight,
-    );
-  }
-
-  void scrollToRect(Rect targetRect) {
-    for (final client in _clients) {
-      client.scrollToRect(targetRect);
-    }
-  }
-
-  /// Width each row in the tree should have ignoring its indent.
-  ///
-  /// Content in rows should wrap if it exceeds this width.
-  final rowWidth = 1200;
-
-  /// Maximum indent of the tree in pixels.
-  double? _maxIndent;
-
-  double get maxRowIndent {
-    if (lastContentWidth == null) {
-      double maxIndent = 0;
-      for (int i = 0; i < numRows; i++) {
-        final row = getCachedRow(i);
-        if (row != null) {
-          maxIndent = max(maxIndent, getDepthIndent(row.depth));
-        }
-      }
-      lastContentWidth = maxIndent + maxIndent;
-      _maxIndent = maxIndent;
-    }
-    return _maxIndent!;
-  }
-
-  void animateToTargets(List<InspectorTreeNode> targets) {
-    Rect? targetRect;
-
-    for (final target in targets) {
-      final row = getRowForNode(target);
-      if (row != null) {
-        final rowRect = getBoundingBox(row);
-        targetRect = targetRect == null
-            ? rowRect
-            : targetRect.expandToInclude(rowRect);
-      }
-    }
-
-    if (targetRect == null || targetRect.isEmpty) return;
-
-    scrollToRect(targetRect);
-  }
-
-  bool expandPropertiesByDefault(DiagnosticsTreeStyle style) {
-    // This code matches the text style defaults for which styles are
-    //  by default and which aren't.
-    switch (style) {
-      case DiagnosticsTreeStyle.none:
-      case DiagnosticsTreeStyle.singleLine:
-      case DiagnosticsTreeStyle.errorProperty:
-        return false;
-
-      case DiagnosticsTreeStyle.sparse:
-      case DiagnosticsTreeStyle.offstage:
-      case DiagnosticsTreeStyle.dense:
-      case DiagnosticsTreeStyle.transition:
-      case DiagnosticsTreeStyle.error:
-      case DiagnosticsTreeStyle.whitespace:
-      case DiagnosticsTreeStyle.flat:
-      case DiagnosticsTreeStyle.shallow:
-      case DiagnosticsTreeStyle.truncateChildren:
-        return true;
-    }
-  }
-
-  InspectorTreeNode setupInspectorTreeNode(
-    InspectorTreeNode node,
-    RemoteDiagnosticsNode diagnosticsNode, {
-    required bool expandChildren,
-    required bool expandProperties,
-  }) {
-    node.diagnostic = diagnosticsNode;
-    final configLocal = config;
-    if (configLocal.onNodeAdded != null) {
-      configLocal.onNodeAdded!(node, diagnosticsNode);
-    }
-
-    if (diagnosticsNode.hasChildren ||
-        diagnosticsNode.inlineProperties.isNotEmpty) {
-      if (diagnosticsNode.childrenReady || !diagnosticsNode.hasChildren) {
-        final styleIsMultiline = expandPropertiesByDefault(
-          diagnosticsNode.style,
-        );
-        setupChildren(
-          diagnosticsNode,
-          node,
-          node.diagnostic!.childrenNow,
-          expandChildren: expandChildren && styleIsMultiline,
-          expandProperties: expandProperties && styleIsMultiline,
-        );
-      } else {
-        node.clearChildren();
-        node.appendChild(createNode());
-      }
-    }
-    return node;
-  }
-
-  void setupChildren(
-    RemoteDiagnosticsNode parent,
-    InspectorTreeNode treeNode,
-    List<RemoteDiagnosticsNode>? children, {
-    required bool expandChildren,
-    required bool expandProperties,
-  }) {
-    treeNode.isExpanded = expandChildren;
-    if (treeNode.children.isNotEmpty) {
-      // Only case supported is this is the loading node.
-      assert(treeNode.children.length == 1);
-      removeNodeFromParent(treeNode.children.first);
-    }
-    final inlineProperties = parent.inlineProperties;
-
-    for (final property in inlineProperties) {
-      appendChild(
-        treeNode,
-        setupInspectorTreeNode(
-          createNode(),
-          property,
-          // We are inside a property so only expand children if
-          // expandProperties is true.
-          expandChildren: expandProperties,
-          expandProperties: expandProperties,
-        ),
-      );
-    }
-    if (children != null) {
-      for (final child in children) {
-        appendChild(
-          treeNode,
-          setupInspectorTreeNode(
-            createNode(),
-            child,
-            expandChildren: expandChildren,
-            expandProperties: expandProperties,
-          ),
-        );
-      }
-    }
-  }
-
-  Future<void> maybePopulateChildren(InspectorTreeNode treeNode) async {
-    final diagnostic = treeNode.diagnostic;
-    if (diagnostic != null &&
-        diagnostic.hasChildren &&
-        (treeNode.hasPlaceholderChildren || treeNode.children.isEmpty)) {
-      try {
-        final children = await diagnostic.children;
-        if (treeNode.hasPlaceholderChildren || treeNode.children.isEmpty) {
-          setupChildren(
-            diagnostic,
-            treeNode,
-            children,
-            expandChildren: true,
-            expandProperties: false,
-          );
-          nodeChanged(treeNode);
-          if (treeNode == selection) {
-            expandPath(treeNode);
-          }
-        }
-      } catch (e, st) {
-        _log.shout(e, e, st);
-      }
-    }
-  }
-
-  /* Search support */
-  @override
-  void onMatchChanged(int index) {
-    onSelectRow(searchMatches.value[index]);
-  }
-
-  @override
-  Duration get debounceDelay => const Duration(milliseconds: 300);
-
-  @override
-  List<InspectorTreeRow> matchesForSearch(
-    String search, {
-    bool searchPreviousMatches = false,
-  }) {
-    final matches = <InspectorTreeRow>[];
-
-    if (searchPreviousMatches) {
-      final previousMatches = searchMatches.value;
-      for (final previousMatch in previousMatches) {
-        if (previousMatch.node.diagnostic!.searchValue.caseInsensitiveContains(
-          search,
-        )) {
-          matches.add(previousMatch);
-        }
-      }
-
-      if (matches.isNotEmpty) return matches;
-    }
-
-    int debugStatsSearchOps = 0;
-    final debugStatsWidgets = _searchableCachedRows.length;
-
-    final inspectorService = serviceConnection.inspectorService;
-    if (search.isEmpty ||
-        inspectorService == null ||
-        inspectorService.isDisposed) {
-      assert(() {
-        debugPrint('Search completed, no search');
-        return true;
-      }());
-      return matches;
-    }
-
-    assert(() {
-      debugPrint('Search started: $_searchTarget');
-      return true;
-    }());
-
-    for (final row in _searchableCachedRows) {
-      final diagnostic = row!.node.diagnostic;
-      if (diagnostic == null) continue;
-
-      // Widget search begin
-      if (_searchTarget == SearchTargetType.widget) {
-        debugStatsSearchOps++;
-        if (diagnostic.searchValue.caseInsensitiveContains(search)) {
-          matches.add(row);
-          continue;
-        }
-      }
-      // Widget search end
-    }
-
-    assert(() {
-      debugPrint(
-        'Search completed with $debugStatsWidgets widgets, $debugStatsSearchOps ops',
-      );
-      return true;
-    }());
-
-    return matches;
-  }
-}
-
-extension RemoteDiagnosticsNodeExtension on RemoteDiagnosticsNode {
-  String get searchValue {
-    final description = toStringShort();
-    final textPreview = json['textPreview'];
-    return textPreview is String
-        ? '$description ${textPreview.replaceAll('\n', ' ')}'
-        : description;
-  }
-}
-
-abstract class InspectorControllerClient {
-  void onChanged();
-
-  void scrollToRect(Rect rect);
-
-  void requestFocus();
-}
-
-class InspectorTree extends StatefulWidget {
-  const InspectorTree({
-    super.key,
-    required this.controller,
-    required this.treeController,
-    this.summaryTreeController,
-    this.isSummaryTree = false,
-    this.widgetErrors,
-    this.screenId,
-  }) : assert(isSummaryTree == (summaryTreeController == null));
-
-  final InspectorController controller;
-
-  final InspectorTreeController? treeController;
-
-  /// Stores the summary tree controller when this instance of [InspectorTree]
-  /// is for the details tree (i.e. when [isSummaryTree] is false).
-  ///
-  /// This value should be null when this instance of [InspectorTree] is for the
-  /// summary tree itself.
-  final InspectorTreeController? summaryTreeController;
-
-  final bool isSummaryTree;
-  final LinkedHashMap<String, InspectableWidgetError>? widgetErrors;
-  final String? screenId;
-
-  @override
-  State<InspectorTree> createState() => _InspectorTreeState();
-}
-
-// AutomaticKeepAlive is necessary so that the tree does not get recreated when we switch tabs.
-class _InspectorTreeState extends State<InspectorTree>
-    with
-        SingleTickerProviderStateMixin,
-        AutomaticKeepAliveClientMixin<InspectorTree>,
-        AutoDisposeMixin
-    implements InspectorControllerClient {
-  InspectorController get controller => widget.controller;
-  InspectorTreeController? get treeController => widget.treeController;
-
-  late ScrollController _scrollControllerY;
-  late ScrollController _scrollControllerX;
-  Future<void>? _currentAnimateY;
-  Rect? _currentAnimateTarget;
-
-  AnimationController? _constraintDisplayController;
-  late FocusNode _focusNode;
-
-  /// When autoscrolling, the number of rows to pad the target location with.
-  static const _scrollPadCount = 3;
-
-  @override
-  void initState() {
-    super.initState();
-    _scrollControllerX = ScrollController();
-    _scrollControllerY = ScrollController();
-    // TODO(devoncarew): Commented out as per flutter/devtools/pull/2001.
-    //_scrollControllerY.addListener(_onScrollYChange);
-    if (widget.isSummaryTree) {
-      _constraintDisplayController = longAnimationController(this);
-    }
-    _focusNode = FocusNode(debugLabel: 'inspector-tree');
-    autoDisposeFocusNode(_focusNode);
-    final mainIsolateState =
-        serviceConnection.serviceManager.isolateManager.mainIsolateState;
-    if (mainIsolateState != null) {
-      callOnceWhenReady<bool>(
-        trigger: mainIsolateState.isPaused,
-        callback: _bindToController,
-        readyWhen: (triggerValue) => !triggerValue,
-      );
-    }
-  }
-
-  @override
-  void didUpdateWidget(InspectorTree oldWidget) {
-    final oldTreeController = oldWidget.treeController;
-    if (oldTreeController != widget.treeController) {
-      oldTreeController?.removeClient(this);
-
-      // TODO(elliette): Figure out if we can remove this. See explanation:
-      // https://github.com/flutter/devtools/pull/1290/files#r342399899.
-      cancelListeners();
-
-      _bindToController();
-    }
-    super.didUpdateWidget(oldWidget);
-  }
-
-  @override
-  void dispose() {
-    treeController?.removeClient(this);
-    _scrollControllerX.dispose();
-    _scrollControllerY.dispose();
-    _constraintDisplayController?.dispose();
-    super.dispose();
-  }
-
-  @override
-  void requestFocus() {
-    _focusNode.requestFocus();
-  }
-
-  // TODO(devoncarew): Commented out as per flutter/devtools/pull/2001.
-  //  void _onScrollYChange() {
-  //    if (controller == null) return;
-  //
-  //    // If the vertical position  is already being animated we should not trigger
-  //    // a new animation of the horizontal position as a more direct animation of
-  //    // the horizontal position has already been triggered.
-  //    if (currentAnimateY != null) return;
-  //
-  //    final x = _computeTargetX(_scrollControllerY.offset);
-  //    _scrollControllerX.animateTo(
-  //      x,
-  //      duration: defaultDuration,
-  //      curve: defaultCurve,
-  //    );
-  //  }
-
-  @override
-  Future<void> scrollToRect(Rect rect) async {
-    if (rect == _currentAnimateTarget) {
-      // We are in the middle of an animation to this exact rectangle.
-      return;
-    }
-
-    final initialX = rect.left;
-    final initialY = rect.top;
-    final yOffsetAtViewportTop = _scrollControllerY.hasClients
-        ? _scrollControllerY.offset
-        : _scrollControllerY.initialScrollOffset;
-    final xOffsetAtViewportLeft = _scrollControllerX.hasClients
-        ? _scrollControllerX.offset
-        : _scrollControllerX.initialScrollOffset;
-
-    final viewPortInScrollControllerSpace = Rect.fromLTWH(
-      xOffsetAtViewportLeft,
-      yOffsetAtViewportTop,
-      safeViewportWidth,
-      safeViewportHeight,
-    );
-
-    final isRectInViewPort =
-        viewPortInScrollControllerSpace.contains(rect.topLeft) &&
-        viewPortInScrollControllerSpace.contains(rect.bottomRight);
-    if (isRectInViewPort) {
-      // The rect is already in view, don't scroll
-      return;
-    }
-
-    _currentAnimateTarget = rect;
-
-    final targetY = _padTargetY(initialY: initialY);
-    if (_scrollControllerY.hasClients) {
-      _currentAnimateY = _scrollControllerY.animateTo(
-        targetY,
-        duration: longDuration,
-        curve: defaultCurve,
-      );
-    } else {
-      _currentAnimateY = null;
-      _scrollControllerY = ScrollController(initialScrollOffset: targetY);
-    }
-
-    final targetX = _padTargetX(initialX: initialX);
-    if (_scrollControllerX.hasClients) {
-      unawaited(
-        _scrollControllerX.animateTo(
-          targetX,
-          duration: longDuration,
-          curve: defaultCurve,
-        ),
-      );
-    } else {
-      _scrollControllerX = ScrollController(initialScrollOffset: targetX);
-    }
-
-    try {
-      await _currentAnimateY;
-    } catch (e) {
-      // Doesn't matter if the animation was cancelled.
-    }
-    _currentAnimateY = null;
-    _currentAnimateTarget = null;
-  }
-
-  // TODO(jacobr): resolve cases where we need to know the viewport height
-  // before it is available so we don't need this approximation.
-  /// Placeholder viewport height to use if we don't yet know the real
-  /// viewport height.
-  static const _placeholderViewportSize = Size(1000.0, 1000.0);
-
-  double get safeViewportHeight {
-    return _scrollControllerY.hasClients
-        ? _scrollControllerY.position.viewportDimension
-        : _placeholderViewportSize.height;
-  }
-
-  double get safeViewportWidth {
-    return _scrollControllerX.hasClients
-        ? _scrollControllerX.position.viewportDimension
-        : _placeholderViewportSize.width;
-  }
-
-  /// Pad [initialX] with the horizontal indentation of [padCount] rows.
-  double _padTargetX({
-    required double initialX,
-    int padCount = _scrollPadCount,
-  }) {
-    return initialX - inspectorColumnWidth * padCount;
-  }
-
-  /// Pad [initialY] so that a row would be placed in the vertical center of
-  /// the screen.
-  double _padTargetY({required double initialY}) {
-    return initialY - (safeViewportHeight / 2) + inspectorRowHeight / 2;
-  }
-
-  /// Handle arrow keys for the InspectorTree. Ignore other key events so that
-  /// other widgets have a chance to respond to them.
-  KeyEventResult _handleKeyEvent(FocusNode _, KeyEvent event) {
-    if (!event.isKeyDownOrRepeat) return KeyEventResult.ignored;
-
-    final treeControllerLocal = treeController!;
-
-    if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
-      treeControllerLocal.navigateDown();
-      return KeyEventResult.handled;
-    } else if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
-      treeControllerLocal.navigateUp();
-      return KeyEventResult.handled;
-    } else if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
-      treeControllerLocal.navigateLeft();
-      return KeyEventResult.handled;
-    } else if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
-      treeControllerLocal.navigateRight();
-      return KeyEventResult.handled;
-    }
-
-    return KeyEventResult.ignored;
-  }
-
-  void _bindToController() {
-    treeController?.addClient(this);
-  }
-
-  @override
-  void onChanged() {
-    setState(() {});
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    super.build(context);
-    final treeControllerLocal = treeController;
-    if (treeControllerLocal == null) {
-      // Indicate the tree is loading.
-      return const CenteredCircularProgressIndicator();
-    }
-    if (treeControllerLocal.numRows == 0) {
-      // This works around a bug when Scrollbars are present on a short lived
-      // widget.
-      return const SizedBox();
-    }
-
-    if (!controller.firstInspectorTreeLoadCompleted && widget.isSummaryTree) {
-      final screenId = widget.screenId;
-      if (screenId != null) {
-        ga.timeEnd(
-          screenId,
-          gac.pageReady,
-          screenMetricsProvider: () => InspectorScreenMetrics.legacy(
-            rowCount: treeControllerLocal.numRows,
-          ),
-        );
-        unawaited(
-          serviceConnection.sendDwdsEvent(
-            screen: screenId,
-            action: gac.pageReady,
-          ),
-        );
-      }
-      controller.firstInspectorTreeLoadCompleted = true;
-    }
-    return LayoutBuilder(
-      builder: (context, constraints) {
-        final viewportWidth = constraints.maxWidth;
-        final tree = Scrollbar(
-          thumbVisibility: true,
-          controller: _scrollControllerX,
-          child: SingleChildScrollView(
-            scrollDirection: Axis.horizontal,
-            controller: _scrollControllerX,
-            child: ConstrainedBox(
-              constraints: BoxConstraints(
-                maxWidth:
-                    treeControllerLocal.rowWidth +
-                    treeControllerLocal.maxRowIndent,
-              ),
-              // TODO(kenz): this scrollbar needs to be sticky to the right side of
-              // the visible container - right now it is lined up to the right of
-              // the widest row (which is likely not visible). This may require some
-              // refactoring.
-              child: GestureDetector(
-                onTap: _focusNode.requestFocus,
-                child: Focus(
-                  onKeyEvent: _handleKeyEvent,
-                  autofocus: widget.isSummaryTree,
-                  focusNode: _focusNode,
-                  child: OffsetScrollbar(
-                    isAlwaysShown: true,
-                    axis: Axis.vertical,
-                    controller: _scrollControllerY,
-                    offsetController: _scrollControllerX,
-                    offsetControllerViewportDimension: viewportWidth,
-                    child: ListView.custom(
-                      itemExtent: inspectorRowHeight,
-                      childrenDelegate: SliverChildBuilderDelegate((
-                        context,
-                        index,
-                      ) {
-                        if (index == treeControllerLocal.numRows) {
-                          return const SizedBox(height: inspectorRowHeight);
-                        }
-                        final row = treeControllerLocal.getCachedRow(index)!;
-                        final inspectorRef = row.node.diagnostic?.valueRef.id;
-                        return _InspectorTreeRowWidget(
-                          key: PageStorageKey(row.node),
-                          inspectorTreeState: this,
-                          row: row,
-                          scrollControllerX: _scrollControllerX,
-                          viewportWidth: viewportWidth,
-                          error:
-                              widget.widgetErrors != null &&
-                                  inspectorRef != null
-                              ? widget.widgetErrors![inspectorRef]
-                              : null,
-                        );
-                      }, childCount: treeControllerLocal.numRows + 1),
-                      controller: _scrollControllerY,
-                    ),
-                  ),
-                ),
-              ),
-            ),
-          ),
-        );
-
-        final shouldShowBreadcrumbs = !widget.isSummaryTree;
-        if (shouldShowBreadcrumbs) {
-          final inspectorTreeController = widget.summaryTreeController!;
-
-          final parents = inspectorTreeController
-              .getPathFromSelectedRowToRoot();
-          return Column(
-            children: [
-              InspectorBreadcrumbNavigator(
-                items: parents,
-                onTap: (node) => inspectorTreeController.onSelectNode(node),
-              ),
-              Expanded(child: tree),
-            ],
-          );
-        }
-
-        return tree;
-      },
-    );
-  }
-
-  @override
-  bool get wantKeepAlive => true;
-}
-
-Paint _defaultPaint(ColorScheme colorScheme) => Paint()
-  ..color = colorScheme.treeGuidelineColor
-  ..strokeWidth = chartLineStrokeWidth;
-
-/// Custom painter that draws lines indicating how parent and child rows are
-/// connected to each other.
-///
-/// Each rows object contains a list of ticks that indicate the x coordinates of
-/// vertical lines connecting other rows need to be drawn within the vertical
-/// area of the current row. This approach has the advantage that a row contains
-/// all information required to render all content within it but has the
-/// disadvantage that the x coordinates of each line connecting rows must be
-/// computed in advance.
-class _RowPainter extends CustomPainter {
-  _RowPainter(this.row, this._controller, this.colorScheme);
-
-  final InspectorTreeController _controller;
-  final InspectorTreeRow row;
-  final ColorScheme colorScheme;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    double currentX = 0;
-    final paint = _defaultPaint(colorScheme);
-
-    final node = row.node;
-    final showExpandCollapse = node.showExpandCollapse;
-    for (final tick in row.ticks) {
-      currentX = _controller.getDepthIndent(tick) - inspectorColumnWidth * 0.5;
-      // Draw a vertical line for each tick identifying a connection between
-      // an ancestor of this node and some other node in the tree.
-      canvas.drawLine(
-        Offset(currentX, 0.0),
-        Offset(currentX, inspectorRowHeight),
-        paint,
-      );
-    }
-    // If this row is itself connected to a parent then draw the L shaped line
-    // to make that connection.
-    if (row.lineToParent) {
-      currentX =
-          _controller.getDepthIndent(row.depth - 1) -
-          inspectorColumnWidth * 0.5;
-      final width = showExpandCollapse
-          ? inspectorColumnWidth * 0.5
-          : inspectorColumnWidth;
-      canvas.drawLine(
-        Offset(currentX, 0.0),
-        Offset(currentX, inspectorRowHeight * 0.5),
-        paint,
-      );
-      canvas.drawLine(
-        Offset(currentX, inspectorRowHeight * 0.5),
-        Offset(currentX + width, inspectorRowHeight * 0.5),
-        paint,
-      );
-    }
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) {
-    if (oldDelegate is _RowPainter) {
-      // TODO(jacobr): check whether the row has different ticks.
-      return oldDelegate.colorScheme.isLight != colorScheme.isLight;
-    }
-    return true;
-  }
-}
-
-/// Widget defining the contents of a single row in the InspectorTree.
-///
-/// This class defines the scaffolding around the rendering of the actual
-/// content of a [RemoteDiagnosticsNode] provided by
-/// [DiagnosticsNodeDescription] to provide a tree implementation with lines
-/// drawn between parent and child nodes when nodes have multiple children.
-///
-/// Changes to how the actual content of the node within the row should
-/// be implemented by changing [DiagnosticsNodeDescription] instead.
-class InspectorRowContent extends StatelessWidget {
-  const InspectorRowContent({
-    super.key,
-    required this.row,
-    required this.controller,
-    required this.onToggle,
-    required this.expandArrowAnimation,
-    this.error,
-    required this.scrollControllerX,
-    required this.viewportWidth,
-  });
-
-  final InspectorTreeRow row;
-  final InspectorTreeController controller;
-  final VoidCallback onToggle;
-  final Animation<double> expandArrowAnimation;
-  final ScrollController scrollControllerX;
-  final double viewportWidth;
-
-  /// A [DevToolsError] that applies to the widget in this row.
-  ///
-  /// This will be null if there is no error for this row.
-  final DevToolsError? error;
-
-  /// Whether this row has any error.
-  bool get hasError => error != null;
-
-  @override
-  Widget build(BuildContext context) {
-    final currentX =
-        controller.getDepthIndent(row.depth) - inspectorColumnWidth;
-    final theme = Theme.of(context);
-    final colorScheme = theme.colorScheme;
-
-    Color? backgroundColor;
-    if (row.isSelected) {
-      backgroundColor = hasError
-          ? colorScheme.errorContainer
-          : colorScheme.selectedRowBackgroundColor;
-    }
-
-    final node = row.node;
-
-    Widget rowWidget = Padding(
-      padding: EdgeInsets.only(left: currentX),
-      child: ValueListenableBuilder<String>(
-        valueListenable: controller.searchNotifier,
-        builder: (context, searchValue, _) {
-          return Opacity(
-            opacity: searchValue.isEmpty || row.isSearchMatch ? 1 : 0.2,
-            child: Row(
-              mainAxisSize: MainAxisSize.min,
-              children: [
-                node.showExpandCollapse
-                    ? InkWell(
-                        onTap: onToggle,
-                        child: RotationTransition(
-                          turns: expandArrowAnimation,
-                          child: const Icon(
-                            Icons.expand_more,
-                            size: defaultIconSize,
-                          ),
-                        ),
-                      )
-                    : const SizedBox(
-                        width: defaultSpacing,
-                        height: defaultSpacing,
-                      ),
-                Expanded(
-                  child: Container(
-                    color: backgroundColor,
-                    child: InkWell(
-                      onTap: () {
-                        controller.onSelectRow(row);
-                        // TODO(gmoothart): It may be possible to capture the tap
-                        // and request focus directly from the InspectorTree. Then
-                        // we wouldn't need this.
-                        controller.requestFocus();
-                      },
-                      child: SizedBox(
-                        height: inspectorRowHeight,
-                        child: DiagnosticsNodeDescription(
-                          node.diagnostic,
-                          isSelected: row.isSelected,
-                          searchValue: searchValue,
-                          errorText: error?.errorMessage,
-                          nodeDescriptionHighlightStyle:
-                              searchValue.isEmpty || !row.isSearchMatch
-                              ? DiagnosticsTextStyles.regular(
-                                  Theme.of(context).colorScheme,
-                                )
-                              : row.isSelected
-                              ? theme.searchMatchHighlightStyleFocused
-                              : theme.searchMatchHighlightStyle,
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ],
-            ),
-          );
-        },
-      ),
-    );
-
-    // Wrap with tooltip if there is an error for this node's widget.
-    if (hasError) {
-      rowWidget = DevToolsTooltip(
-        message: error!.errorMessage,
-        child: rowWidget,
-      );
-    }
-
-    return CustomPaint(
-      painter: _RowPainter(row, controller, colorScheme),
-      size: Size(currentX, inspectorRowHeight),
-      child: Align(
-        alignment: Alignment.topLeft,
-        child: AnimatedBuilder(
-          animation: scrollControllerX,
-          builder: (context, child) {
-            final rowWidth =
-                scrollControllerX.offset + viewportWidth - defaultSpacing;
-            return SizedBox(
-              width: max(rowWidth, currentX + 100),
-              child: rowWidth > currentX ? child : const SizedBox(),
-            );
-          },
-          child: rowWidget,
-        ),
-      ),
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart
deleted file mode 100644
index ff57992..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart
+++ /dev/null
@@ -1,446 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-import 'dart:math' as math;
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../../../shared/diagnostics/diagnostics_node.dart';
-import '../../../../shared/primitives/math_utils.dart';
-import '../../../../shared/primitives/utils.dart';
-import '../../inspector_data_models.dart';
-import '../ui/free_space.dart';
-import '../ui/layout_explorer_widget.dart';
-import '../ui/theme.dart';
-import '../ui/utils.dart';
-import '../ui/widget_constraints.dart';
-import '../ui/widgets_theme.dart';
-
-/// Layout visualizer for a widget with a box-layout.
-class BoxLayoutExplorerWidget extends LayoutExplorerWidget {
-  const BoxLayoutExplorerWidget(super.inspectorController, {super.key});
-
-  static bool shouldDisplay(RemoteDiagnosticsNode _) {
-    // Pretend this layout explorer is always available. This layout explorer
-    // will gracefully fall back to an error message if the required properties
-    // are not needed.
-    // TODO(jacobr) pass a RemoteDiagnosticsNode to this method that contains
-    // the layout explorer related supplemental properties so that we can
-    // accurately determine whether the widget uses box layout.
-    return true;
-  }
-
-  @override
-  State<BoxLayoutExplorerWidget> createState() =>
-      BoxLayoutExplorerWidgetState();
-}
-
-class BoxLayoutExplorerWidgetState
-    extends
-        LayoutExplorerWidgetState<BoxLayoutExplorerWidget, LayoutProperties> {
-  @override
-  RemoteDiagnosticsNode? getRoot(RemoteDiagnosticsNode? node) {
-    final nodeLocal = node;
-    if (nodeLocal == null) return null;
-    if (!shouldDisplay(nodeLocal)) return null;
-    return node;
-  }
-
-  @override
-  bool shouldDisplay(RemoteDiagnosticsNode node) {
-    final selectedNodeLocal = selectedNode;
-    if (selectedNodeLocal == null) return false;
-    return BoxLayoutExplorerWidget.shouldDisplay(selectedNodeLocal);
-  }
-
-  @override
-  AnimatedLayoutProperties computeAnimatedProperties(
-    LayoutProperties nextProperties,
-  ) {
-    return AnimatedLayoutProperties(
-      // If an animation is in progress, freeze it and start animating from there, else start a fresh animation from widget.properties.
-      animatedProperties?.copyWith() ?? properties!,
-      nextProperties,
-      changeAnimation,
-    );
-  }
-
-  @override
-  LayoutProperties computeLayoutProperties(RemoteDiagnosticsNode node) =>
-      LayoutProperties(node);
-
-  @override
-  void updateHighlighted(LayoutProperties? newProperties) {
-    setState(() {
-      // This implementation will need to change if we support showing more than
-      // a single widget in the box visualization for the layout explorer.
-      highlighted = newProperties != null && selectedNode == newProperties.node
-          ? newProperties
-          : null;
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (properties == null) {
-      final selectedNodeLocal = selectedNode;
-      return Center(
-        child: Text(
-          '${selectedNodeLocal?.description ?? 'Widget'} has no layout properties to display.',
-          textAlign: TextAlign.center,
-          overflow: TextOverflow.clip,
-        ),
-      );
-    }
-    return Container(
-      margin: const EdgeInsets.all(denseSpacing),
-      child: AnimatedBuilder(
-        animation: changeController,
-        builder: (context, _) {
-          return LayoutBuilder(builder: _buildLayout);
-        },
-      ),
-    );
-  }
-
-  /// Simplistic layout algorithm to roughly match minFraction restrictions for
-  /// each sizes attempting to render a stylized version of the original layout.
-  /// TODO(jacobr): see if we can unify with the stylized version of the overall
-  /// layout used for Flex. Our constraints are quite different as we can
-  /// guarantee that the entire layout fits without scrolling while in the Flex
-  /// case that would be difficult.
-  ///
-  /// The overall layout will expand to use the full availableSize treating null
-  /// values in [sizes] as an indication that the items should have zero size.
-  /// On the other hand, a non-null size indicates that the minFractions
-  /// constraints should be obeyed. This is needed to ensure that negative sizes
-  /// are visualized reasonably.
-  /// The minFractions aren't exactly obeyed but they are approximated in a way
-  /// that keeps this algorithm simple and has the nice property that an initial
-  /// value much smaller than the minSize results in a slightly smaller value
-  /// than a value that is almost minSize.
-  /// In the most extreme case an item will get not minFraction but will instead
-  /// get the slightly smaller value of minFraction / (1 + minFraction)
-  /// which is close enough for the simple values we need this for.
-  static List<double> minFractionLayout({
-    required double availableSize,
-    required List<double?> sizes,
-    required List<double> minFractions,
-  }) {
-    assert(sizes.length == minFractions.length);
-    final length = sizes.length;
-    double total = 1.0; // This isn't set to zero to avoid divide by zero bugs.
-    final fractions = minFractions.toList();
-    for (final size in sizes) {
-      if (size != null) {
-        total += math.max(0, size);
-      }
-    }
-
-    double totalFraction = 0.0;
-    for (int i = 0; i < length; i++) {
-      final size = sizes[i];
-      if (size != null) {
-        fractions[i] = math.max(size / total, minFractions[i]);
-        totalFraction += fractions[i];
-      } else {
-        fractions[i] = 0.0;
-      }
-    }
-    if (totalFraction != 1.0) {
-      for (int i = 0; i < length; i++) {
-        fractions[i] = fractions[i] / totalFraction;
-      }
-    }
-    final output = <double>[];
-    for (final fraction in fractions) {
-      output.add(fraction * availableSize);
-    }
-    return output;
-  }
-
-  Widget _buildChild(BuildContext context) {
-    final propertiesLocal = properties!;
-
-    final theme = Theme.of(context);
-    final colorScheme = theme.colorScheme;
-    final parentProperties =
-        this.parentProperties ??
-        propertiesLocal; // Fall back to this node's properties if there is no parent.
-
-    final parentSize = parentProperties.size;
-    final offset = propertiesLocal.node.parentData;
-
-    return LayoutBuilder(
-      builder: (BuildContext context, BoxConstraints constraints) {
-        // Subtract out one pixel border on each side.
-        final availableHeight = constraints.maxHeight - 2;
-        final availableWidth = constraints.maxWidth - 2;
-
-        final minFractions = [0.2, 0.5, 0.2];
-        // TODO(polinach, jacobr): consider using zeros for zero values,
-        // without replacing them with nulls.
-        // See https://github.com/flutter/devtools/issues/3931.
-        double? nullOutZero(double value) => value != 0.0 ? value : null;
-        final widths = [
-          nullOutZero(offset.offset.dx),
-          propertiesLocal.size.width,
-          nullOutZero(
-            parentSize.width - (propertiesLocal.size.width + offset.offset.dx),
-          ),
-        ];
-        final heights = [
-          nullOutZero(offset.offset.dy),
-          propertiesLocal.size.height,
-          nullOutZero(
-            parentSize.height -
-                (propertiesLocal.size.height + offset.offset.dy),
-          ),
-        ];
-        // 3 element array with [left padding, widget width, right padding].
-        final displayWidths = minFractionLayout(
-          availableSize: availableWidth,
-          sizes: widths,
-          minFractions: minFractions,
-        );
-        // 3 element array with [top padding, widget height, bottom padding].
-        final displayHeights = minFractionLayout(
-          availableSize: availableHeight,
-          sizes: heights,
-          minFractions: minFractions,
-        );
-        final widgetWidth = displayWidths[1];
-        final widgetHeight = displayHeights[1];
-        final safeParentSize = parentSize;
-        final width0 = widths[0];
-        final width2 = widths[2];
-        final height0 = heights[0];
-        final height2 = heights[2];
-        return Container(
-          width: constraints.maxWidth,
-          height: constraints.maxHeight,
-          decoration: BoxDecoration(
-            border: Border.all(
-              color: WidgetTheme.fromName(
-                propertiesLocal.node.description,
-              ).color,
-            ),
-          ),
-          child: Stack(
-            children: [
-              LayoutExplorerBackground(colorScheme: colorScheme),
-              // Left padding.
-              if (width0 != null)
-                PaddingVisualizerWidget(
-                  RenderProperties(
-                    axis: Axis.horizontal,
-                    size: Size(displayWidths[0], widgetHeight),
-                    offset: Offset(0, displayHeights[0]),
-                    realSize: Size(width0, safeParentSize.height),
-                    layoutProperties: propertiesLocal,
-                    isFreeSpace: true,
-                  ),
-                  horizontal: true,
-                ),
-              // Top padding.
-              if (height0 != null)
-                PaddingVisualizerWidget(
-                  RenderProperties(
-                    axis: Axis.horizontal,
-                    size: Size(widgetWidth, displayHeights[0]),
-                    offset: Offset(displayWidths[0], 0),
-                    realSize: Size(safeParentSize.width, height0),
-                    layoutProperties: propertiesLocal,
-                    isFreeSpace: true,
-                  ),
-                  horizontal: false,
-                ),
-              // Right padding.
-              if (width2 != null)
-                PaddingVisualizerWidget(
-                  RenderProperties(
-                    axis: Axis.horizontal,
-                    size: Size(displayWidths[2], widgetHeight),
-                    offset: Offset(
-                      displayWidths[0] + displayWidths[1],
-                      displayHeights[0],
-                    ),
-                    realSize: Size(width2, safeParentSize.height),
-                    layoutProperties: propertiesLocal,
-                    isFreeSpace: true,
-                  ),
-                  horizontal: true,
-                ),
-              // Bottom padding.
-              if (height2 != null)
-                PaddingVisualizerWidget(
-                  RenderProperties(
-                    axis: Axis.horizontal,
-                    size: Size(widgetWidth, displayHeights[2]),
-                    offset: Offset(
-                      displayWidths[0],
-                      displayHeights[0] + displayHeights[1],
-                    ),
-                    realSize: Size(safeParentSize.width, height2),
-                    layoutProperties: propertiesLocal,
-                    isFreeSpace: true,
-                  ),
-                  horizontal: false,
-                ),
-              BoxChildVisualizer(
-                isSelected: true,
-                state: this,
-                layoutProperties: propertiesLocal,
-                renderProperties: RenderProperties(
-                  axis: Axis.horizontal,
-                  size: Size(widgetWidth, widgetHeight),
-                  offset: Offset(displayWidths[0], displayHeights[0]),
-                  realSize: propertiesLocal.size,
-                  layoutProperties: propertiesLocal,
-                ),
-              ),
-            ],
-          ),
-        );
-      },
-    );
-  }
-
-  LayoutProperties? get parentProperties {
-    final parentElement = properties?.node.parentRenderElement;
-    if (parentElement == null) return null;
-    return computeLayoutProperties(parentElement);
-  }
-
-  Widget _buildLayout(BuildContext context, BoxConstraints constraints) {
-    final maxHeight = constraints.maxHeight;
-    final maxWidth = constraints.maxWidth;
-
-    Widget widget = _buildChild(context);
-    final parentProperties = this.parentProperties;
-    if (parentProperties != null) {
-      // Wrap with a widget visualizer for the parent if there is a valid parent.
-      widget = WidgetVisualizer(
-        // TODO(jacobr): this node's name can be misleading more often than
-        // in the flex case the widget doesn't have its own RenderObject.
-        // Consider showing the true ancestor for the summary tree that first
-        // has a different render object.
-        title: describeBoxName(parentProperties),
-        largeTitle: true,
-        layoutProperties: parentProperties,
-        isSelected: false,
-        child: VisualizeWidthAndHeightWithConstraints(
-          properties: parentProperties,
-          warnIfUnconstrained: false,
-          child: Padding(
-            padding: const EdgeInsets.all(denseSpacing),
-            child: widget,
-          ),
-        ),
-      );
-    }
-    return Container(
-      constraints: BoxConstraints(maxWidth: maxWidth, maxHeight: maxHeight),
-      child: widget,
-    );
-  }
-}
-
-String describeBoxName(LayoutProperties properties) {
-  // Displaying a high quality name is more ambiguous for the Box case than the
-  // Flex case because the RenderObject for each widget is often quite
-  // different than the user expected as not all widgets have RenderObjects.
-  // As a compromise we currently show 'WidgetName - RenderObjectName'.
-  // This is clearer but risks more confusion
-
-  // Widget name.
-  var title = properties.node.description ?? '';
-  final renderDescription = properties.node.renderObject?.description;
-  // TODO(jacobr): consider de-emphasizing the render object name by putting it
-  // in more transparent text or just calling the widget Parent instead of
-  // surfacing a widget name.
-  if (renderDescription != null) {
-    // Name of the associated RenderObject if one is available.
-    title += ' - $renderDescription';
-  }
-  return title;
-}
-
-/// Widget that represents and visualize a direct child of Flex widget.
-class BoxChildVisualizer extends StatelessWidget {
-  const BoxChildVisualizer({
-    super.key,
-    required this.state,
-    required this.layoutProperties,
-    required this.renderProperties,
-    required this.isSelected,
-  });
-
-  final BoxLayoutExplorerWidgetState state;
-
-  final bool isSelected;
-  final LayoutProperties layoutProperties;
-  final RenderProperties renderProperties;
-
-  LayoutProperties? get properties => renderProperties.layoutProperties;
-
-  @override
-  Widget build(BuildContext context) {
-    final renderSize = renderProperties.size;
-    final renderOffset = renderProperties.offset;
-
-    Widget buildEntranceAnimation(BuildContext _, Widget? child) {
-      final size = renderSize;
-      // TODO(jacobr): does this entrance animation really add value.
-      return Opacity(
-        opacity: min([state.entranceCurve.value * 5, 1.0]),
-        child: Padding(
-          padding: EdgeInsets.symmetric(
-            horizontal: math.max(0.0, (renderSize.width - size.width) / 2),
-            vertical: math.max(0.0, (renderSize.height - size.height) / 2),
-          ),
-          child: child,
-        ),
-      );
-    }
-
-    final propertiesLocal = properties!;
-
-    return Positioned(
-      top: renderOffset.dy,
-      left: renderOffset.dx,
-      child: InkWell(
-        onTap: () => unawaited(state.onTap(propertiesLocal)),
-        onDoubleTap: () => state.onDoubleTap(propertiesLocal),
-        child: SizedBox(
-          width: safePositiveDouble(renderSize.width),
-          height: safePositiveDouble(renderSize.height),
-          child: AnimatedBuilder(
-            animation: state.entranceController,
-            builder: buildEntranceAnimation,
-            child: WidgetVisualizer(
-              isSelected: isSelected,
-              layoutProperties: layoutProperties,
-              title: describeBoxName(propertiesLocal),
-              // TODO(jacobr): consider surfacing the overflow size information
-              // if we determine
-              // overflowSide: properties.overflowSide,
-
-              // We only show one child at a time so a large title is safe.
-              largeTitle: true,
-              child: VisualizeWidthAndHeightWithConstraints(
-                arrowHeadSize: arrowHeadSize,
-                properties: propertiesLocal,
-                warnIfUnconstrained: false,
-                child: const SizedBox.shrink(),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart
deleted file mode 100644
index c00d352..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/flex.dart
+++ /dev/null
@@ -1,777 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-import 'dart:math' as math;
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../../../shared/diagnostics/diagnostics_node.dart';
-import '../../../../shared/diagnostics/inspector_service.dart';
-import '../../../../shared/primitives/math_utils.dart';
-import '../../../../shared/ui/common_widgets.dart';
-import '../../inspector_data_models.dart';
-import '../ui/arrow.dart';
-import '../ui/free_space.dart';
-import '../ui/layout_explorer_widget.dart';
-import '../ui/theme.dart';
-import '../ui/utils.dart';
-import '../ui/widget_constraints.dart';
-import 'utils.dart';
-
-// TODO(kenz): clean up this file so that we use helper widgets instead of
-// methods that pass around build context.
-
-// TODO(kenz): densify the layout explorer visualization for flex widgets.
-
-const alignmentDropdownMaxSize = 140.0;
-
-class FlexLayoutExplorerWidget extends LayoutExplorerWidget {
-  const FlexLayoutExplorerWidget(super.inspectorController, {super.key});
-
-  static bool shouldDisplay(RemoteDiagnosticsNode node) {
-    return (node.isFlex) || (node.parent?.isFlex ?? false);
-  }
-
-  @override
-  State<FlexLayoutExplorerWidget> createState() =>
-      FlexLayoutExplorerWidgetState();
-}
-
-class FlexLayoutExplorerWidgetState
-    extends
-        LayoutExplorerWidgetState<
-          FlexLayoutExplorerWidget,
-          FlexLayoutProperties
-        > {
-  final scrollController = ScrollController();
-
-  Axis get direction => properties!.direction;
-
-  ObjectGroup? get objectGroup =>
-      properties!.node.objectGroupApi as ObjectGroup?;
-
-  Color horizontalColor(ColorScheme colorScheme) =>
-      properties!.isMainAxisHorizontal
-      ? colorScheme.mainAxisColor
-      : colorScheme.crossAxisColor;
-
-  Color verticalColor(ColorScheme colorScheme) => properties!.isMainAxisVertical
-      ? colorScheme.mainAxisColor
-      : colorScheme.crossAxisColor;
-
-  Color horizontalTextColor(ColorScheme colorScheme) =>
-      properties!.isMainAxisHorizontal
-      ? colorScheme.mainAxisTextColor
-      : colorScheme.crossAxisTextColor;
-
-  Color verticalTextColor(ColorScheme colorScheme) =>
-      properties!.isMainAxisVertical
-      ? colorScheme.mainAxisTextColor
-      : colorScheme.crossAxisTextColor;
-
-  String get flexType => properties!.type;
-
-  @override
-  RemoteDiagnosticsNode? getRoot(RemoteDiagnosticsNode? node) {
-    if (node == null) return null;
-    if (!shouldDisplay(node)) return null;
-    if (node.isFlex) return node;
-    return node.parent;
-  }
-
-  @override
-  bool shouldDisplay(RemoteDiagnosticsNode node) {
-    final selectedNodeLocal = selectedNode;
-    if (selectedNodeLocal == null) return false;
-    return FlexLayoutExplorerWidget.shouldDisplay(selectedNodeLocal);
-  }
-
-  @override
-  AnimatedFlexLayoutProperties computeAnimatedProperties(
-    FlexLayoutProperties nextProperties,
-  ) {
-    return AnimatedFlexLayoutProperties(
-      // If an animation is in progress, freeze it and start animating from there, else start a fresh animation from widget.properties.
-      animatedProperties?.copyWith() as FlexLayoutProperties? ?? properties!,
-      nextProperties,
-      changeAnimation,
-    );
-  }
-
-  @override
-  FlexLayoutProperties computeLayoutProperties(RemoteDiagnosticsNode node) =>
-      FlexLayoutProperties.fromDiagnostics(node);
-
-  @override
-  void updateHighlighted(FlexLayoutProperties? newProperties) {
-    setState(() {
-      if (selectedNode!.isFlex) {
-        highlighted = newProperties;
-      } else {
-        final idx =
-            selectedNode?.parent?.childrenNow.indexOf(selectedNode!) ?? -1;
-        if (newProperties == null) return;
-        if (idx != -1) highlighted = newProperties.children[idx];
-      }
-    });
-  }
-
-  Widget _buildAxisAlignmentDropdown(Axis axis, ThemeData theme) {
-    final colorScheme = theme.colorScheme;
-    final color = axis == direction
-        ? colorScheme.mainAxisTextColor
-        : colorScheme.crossAxisTextColor;
-    List<Enum> alignmentEnumEntries;
-    Object? selected;
-    final propertiesLocal = properties!;
-    if (axis == direction) {
-      alignmentEnumEntries = MainAxisAlignment.values;
-      selected = propertiesLocal.mainAxisAlignment;
-    } else {
-      alignmentEnumEntries = CrossAxisAlignment.values.toList(growable: true);
-      if (propertiesLocal.textBaseline == null) {
-        // TODO(albertusangga): Look for ways to visualize baseline when it is null
-        alignmentEnumEntries.remove(CrossAxisAlignment.baseline);
-      }
-      selected = propertiesLocal.crossAxisAlignment;
-    }
-    return RotatedBox(
-      quarterTurns: axis == Axis.vertical ? 3 : 0,
-      child: Container(
-        constraints: const BoxConstraints(
-          maxWidth: alignmentDropdownMaxSize,
-          maxHeight: defaultButtonHeight,
-        ),
-        child: DropdownButton(
-          value: selected,
-          isDense: true,
-          isExpanded: true,
-          // Avoid showing an underline for the main axis and cross-axis drop downs.
-          underline: const SizedBox(),
-          iconEnabledColor: axis == propertiesLocal.direction
-              ? colorScheme.mainAxisColor
-              : colorScheme.crossAxisColor,
-          selectedItemBuilder: (context) {
-            return [
-              for (final alignment in alignmentEnumEntries)
-                Row(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: [
-                    Expanded(
-                      child: Text(
-                        alignment.name,
-                        style: theme.regularTextStyleWithColor(color),
-                        textAlign: TextAlign.center,
-                        overflow: TextOverflow.ellipsis,
-                      ),
-                    ),
-                    SizedBox(
-                      height: actionsIconSize,
-                      width: actionsIconSize,
-                      child: Image.asset(
-                        (axis == direction)
-                            ? mainAxisAssetImageUrl(
-                                direction,
-                                alignment as MainAxisAlignment,
-                              )
-                            : crossAxisAssetImageUrl(
-                                direction,
-                                alignment as CrossAxisAlignment,
-                              ),
-                        height: axisAlignmentAssetImageHeight,
-                        fit: BoxFit.fitHeight,
-                        color: color,
-                      ),
-                    ),
-                  ],
-                ),
-            ];
-          },
-          items: [
-            for (final alignment in alignmentEnumEntries)
-              DropdownMenuItem(
-                value: alignment,
-                child: Container(
-                  padding: const EdgeInsets.symmetric(vertical: margin),
-                  child: Row(
-                    mainAxisAlignment: MainAxisAlignment.end,
-                    children: [
-                      Expanded(
-                        child: Text(
-                          alignment.name,
-                          style: theme.regularTextStyleWithColor(color),
-                          textAlign: TextAlign.center,
-                          overflow: TextOverflow.ellipsis,
-                        ),
-                      ),
-                      SizedBox(
-                        height: actionsIconSize,
-                        width: actionsIconSize,
-                        child: Image.asset(
-                          (axis == direction)
-                              ? mainAxisAssetImageUrl(
-                                  direction,
-                                  alignment as MainAxisAlignment,
-                                )
-                              : crossAxisAssetImageUrl(
-                                  direction,
-                                  alignment as CrossAxisAlignment,
-                                ),
-                          fit: BoxFit.fitHeight,
-                          color: color,
-                        ),
-                      ),
-                    ],
-                  ),
-                ),
-              ),
-          ],
-          onChanged: (Object? newSelection) async {
-            // newSelection is an object instead of type here because
-            // the type is dependent on the `axis` parameter
-            // if the axis is the main axis the type should be [MainAxisAlignment]
-            // if the axis is the cross axis the type should be [CrossAxisAlignment]
-            FlexLayoutProperties changedProperties;
-            changedProperties = axis == direction
-                ? propertiesLocal.copyWith(
-                    mainAxisAlignment: newSelection as MainAxisAlignment?,
-                  )
-                : propertiesLocal.copyWith(
-                    crossAxisAlignment: newSelection as CrossAxisAlignment?,
-                  );
-            final valueRef = propertiesLocal.node.valueRef;
-            markAsDirty();
-            await objectGroup!.invokeSetFlexProperties(
-              valueRef,
-              changedProperties.mainAxisAlignment,
-              changedProperties.crossAxisAlignment,
-            );
-          },
-        ),
-      ),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (properties == null) return const SizedBox();
-    return Container(
-      margin: const EdgeInsets.all(margin),
-      padding: const EdgeInsets.only(bottom: margin, right: margin),
-      child: AnimatedBuilder(
-        animation: changeController,
-        builder: (context, _) {
-          return LayoutBuilder(builder: _buildLayout);
-        },
-      ),
-    );
-  }
-
-  Widget _buildLayout(BuildContext context, BoxConstraints constraints) {
-    final theme = Theme.of(context);
-    final colorScheme = theme.colorScheme;
-    final maxHeight = constraints.maxHeight;
-    final maxWidth = constraints.maxWidth;
-    final propertiesLocal = properties!;
-    final flexDescription = Align(
-      alignment: Alignment.centerLeft,
-      child: Container(
-        margin: const EdgeInsets.only(
-          top: mainAxisArrowIndicatorSize,
-          left: crossAxisArrowIndicatorSize + margin,
-        ),
-        child: InkWell(
-          onTap: () => unawaited(onTap(propertiesLocal)),
-          child: WidgetVisualizer(
-            title: flexType,
-            layoutProperties: propertiesLocal,
-            isSelected: highlighted == properties,
-            overflowSide: propertiesLocal.overflowSide,
-            hint: Container(
-              padding: const EdgeInsets.all(4.0),
-              child: Text(
-                'Total Flex Factor: ${propertiesLocal.totalFlex.toInt()}',
-                style: theme.regularTextStyleWithColor(emphasizedTextColor),
-                overflow: TextOverflow.ellipsis,
-              ),
-            ),
-            child: VisualizeFlexChildren(
-              state: this,
-              properties: propertiesLocal,
-              children: children,
-              highlighted: highlighted,
-              scrollController: scrollController,
-              direction: direction,
-            ),
-          ),
-        ),
-      ),
-    );
-
-    final verticalAxisDescription = Align(
-      alignment: Alignment.bottomLeft,
-      child: Container(
-        margin: const EdgeInsets.only(top: mainAxisArrowIndicatorSize + margin),
-        width: crossAxisArrowIndicatorSize,
-        child: Column(
-          children: [
-            Expanded(
-              child: ArrowWrapper.unidirectional(
-                arrowColor: verticalColor(colorScheme),
-                type: ArrowType.down,
-                child: Truncateable(
-                  truncate: maxHeight <= minHeightToAllowTruncating,
-                  child: RotatedBox(
-                    quarterTurns: 3,
-                    child: Text(
-                      propertiesLocal.verticalDirectionDescription,
-                      overflow: TextOverflow.ellipsis,
-                      textAlign: TextAlign.center,
-                      style: theme.regularTextStyleWithColor(
-                        verticalTextColor(colorScheme),
-                      ),
-                    ),
-                  ),
-                ),
-              ),
-            ),
-            Truncateable(
-              truncate: maxHeight <= minHeightToAllowTruncating,
-              child: _buildAxisAlignmentDropdown(Axis.vertical, theme),
-            ),
-          ],
-        ),
-      ),
-    );
-
-    final horizontalAxisDescription = Align(
-      alignment: Alignment.topRight,
-      child: Container(
-        margin: const EdgeInsets.only(
-          left: crossAxisArrowIndicatorSize + margin,
-        ),
-        height: mainAxisArrowIndicatorSize,
-        child: Row(
-          children: [
-            Expanded(
-              child: ArrowWrapper.unidirectional(
-                arrowColor: horizontalColor(colorScheme),
-                type: ArrowType.right,
-                child: Truncateable(
-                  truncate: maxWidth <= minWidthToAllowTruncating,
-                  child: Text(
-                    propertiesLocal.horizontalDirectionDescription,
-                    overflow: TextOverflow.ellipsis,
-                    textAlign: TextAlign.center,
-                    style: theme.regularTextStyleWithColor(
-                      horizontalTextColor(colorScheme),
-                    ),
-                  ),
-                ),
-              ),
-            ),
-            Truncateable(
-              truncate: maxWidth <= minWidthToAllowTruncating,
-              child: _buildAxisAlignmentDropdown(Axis.horizontal, theme),
-            ),
-          ],
-        ),
-      ),
-    );
-
-    return Container(
-      constraints: BoxConstraints(maxWidth: maxWidth, maxHeight: maxHeight),
-      child: Stack(
-        children: [
-          flexDescription,
-          verticalAxisDescription,
-          horizontalAxisDescription,
-        ],
-      ),
-    );
-  }
-}
-
-class VisualizeFlexChildren extends StatefulWidget {
-  const VisualizeFlexChildren({
-    super.key,
-    required this.state,
-    required this.properties,
-    required this.children,
-    required this.highlighted,
-    required this.scrollController,
-    required this.direction,
-  });
-
-  final FlexLayoutProperties properties;
-  final List<LayoutProperties> children;
-  final LayoutProperties? highlighted;
-  final ScrollController scrollController;
-  final Axis direction;
-  final FlexLayoutExplorerWidgetState state;
-
-  @override
-  State<VisualizeFlexChildren> createState() => _VisualizeFlexChildrenState();
-}
-
-class _VisualizeFlexChildrenState extends State<VisualizeFlexChildren> {
-  LayoutProperties? lastHighlighted;
-  static final selectedChildKey = GlobalKey(debugLabel: 'selectedChild');
-
-  @override
-  Widget build(BuildContext context) {
-    if (lastHighlighted != widget.highlighted) {
-      lastHighlighted = widget.highlighted;
-      if (widget.highlighted != null) {
-        WidgetsBinding.instance.addPostFrameCallback((_) {
-          final selectedRenderObject = selectedChildKey.currentContext
-              ?.findRenderObject();
-          if (selectedRenderObject != null &&
-              widget.scrollController.hasClients) {
-            unawaited(
-              widget.scrollController.position.ensureVisible(
-                selectedRenderObject,
-                alignment: 0.5,
-                duration: defaultDuration,
-              ),
-            );
-          }
-        });
-      }
-    }
-
-    if (!widget.properties.hasChildren) {
-      return const CenteredMessage(message: 'No Children');
-    }
-
-    final theme = Theme.of(context);
-    final colorScheme = theme.colorScheme;
-
-    final contents = Container(
-      decoration: BoxDecoration(
-        border: Border.all(color: theme.primaryColorLight),
-      ),
-      margin: const EdgeInsets.only(top: margin, left: margin),
-      child: LayoutBuilder(
-        builder: (context, constraints) {
-          final maxWidth = constraints.maxWidth;
-          final maxHeight = constraints.maxHeight;
-
-          double maxSizeAvailable(Axis axis) {
-            return axis == Axis.horizontal ? maxWidth : maxHeight;
-          }
-
-          final childrenAndMainAxisSpacesRenderProps = widget.properties
-              .childrenRenderProperties(
-                smallestRenderWidth: minRenderWidth,
-                largestRenderWidth: defaultMaxRenderWidth,
-                smallestRenderHeight: minRenderHeight,
-                largestRenderHeight: defaultMaxRenderHeight,
-                maxSizeAvailable: maxSizeAvailable,
-              );
-
-          final renderProperties = childrenAndMainAxisSpacesRenderProps
-              .where((renderProps) => !renderProps.isFreeSpace)
-              .toList();
-          final mainAxisSpaces = childrenAndMainAxisSpacesRenderProps
-              .where((renderProps) => renderProps.isFreeSpace)
-              .toList();
-          final crossAxisSpaces = widget.properties.crossAxisSpaces(
-            childrenRenderProperties: renderProperties,
-            maxSizeAvailable: maxSizeAvailable,
-          );
-
-          final childrenRenderWidgets = <Widget>[];
-          Widget? selectedWidget;
-          for (var i = 0; i < widget.children.length; i++) {
-            final child = widget.children[i];
-            final isSelected = widget.highlighted == child;
-
-            final visualizer = FlexChildVisualizer(
-              key: isSelected ? selectedChildKey : null,
-              state: widget.state,
-              layoutProperties: child,
-              isSelected: isSelected,
-              renderProperties: renderProperties[i],
-            );
-
-            if (isSelected) {
-              selectedWidget = visualizer;
-            } else {
-              childrenRenderWidgets.add(visualizer);
-            }
-          }
-
-          // Selected widget needs to be last to draw its border over other children
-          if (selectedWidget != null) {
-            childrenRenderWidgets.add(selectedWidget);
-          }
-
-          final freeSpacesWidgets = [
-            for (final renderProperties in [
-              ...mainAxisSpaces,
-              ...crossAxisSpaces,
-            ])
-              FreeSpaceVisualizerWidget(renderProperties),
-          ];
-          return Scrollbar(
-            thumbVisibility: true,
-            controller: widget.scrollController,
-            child: SingleChildScrollView(
-              scrollDirection: widget.properties.direction,
-              controller: widget.scrollController,
-              child: ConstrainedBox(
-                constraints: BoxConstraints(
-                  minWidth: maxWidth,
-                  minHeight: maxHeight,
-                  maxWidth: widget.direction == Axis.horizontal
-                      ? sum(
-                          childrenAndMainAxisSpacesRenderProps.map(
-                            (renderSize) => renderSize.width,
-                          ),
-                        )
-                      : maxWidth,
-                  maxHeight: widget.direction == Axis.vertical
-                      ? sum(
-                          childrenAndMainAxisSpacesRenderProps.map(
-                            (renderSize) => renderSize.height,
-                          ),
-                        )
-                      : maxHeight,
-                ).normalize(),
-                child: Stack(
-                  children: [
-                    LayoutExplorerBackground(colorScheme: colorScheme),
-                    ...freeSpacesWidgets,
-                    ...childrenRenderWidgets,
-                  ],
-                ),
-              ),
-            ),
-          );
-        },
-      ),
-    );
-    return VisualizeWidthAndHeightWithConstraints(
-      properties: widget.properties,
-      child: contents,
-    );
-  }
-}
-
-/// Widget that represents and visualize a direct child of Flex widget.
-class FlexChildVisualizer extends StatelessWidget {
-  const FlexChildVisualizer({
-    super.key,
-    required this.state,
-    required this.layoutProperties,
-    required this.renderProperties,
-    required this.isSelected,
-  });
-
-  final FlexLayoutExplorerWidgetState state;
-
-  final bool isSelected;
-
-  final LayoutProperties layoutProperties;
-
-  final RenderProperties renderProperties;
-
-  // TODO(polina-c, jacob314): consider refactoring to remove `!`.
-  FlexLayoutProperties get root => state.properties!;
-
-  LayoutProperties get properties => renderProperties.layoutProperties;
-
-  ObjectGroup? get objectGroup =>
-      properties.node.objectGroupApi as ObjectGroup?;
-
-  void onChangeFlexFactor(int? newFlexFactor) async {
-    state.markAsDirty();
-    await objectGroup!.invokeSetFlexFactor(
-      properties.node.valueRef,
-      newFlexFactor,
-    );
-  }
-
-  void onChangeFlexFit(FlexFit? newFlexFit) async {
-    state.markAsDirty();
-    await objectGroup!.invokeSetFlexFit(properties.node.valueRef, newFlexFit!);
-  }
-
-  Widget _buildFlexFactorChangerDropdown(
-    int maximumFlexFactor,
-    ThemeData theme,
-  ) {
-    final propertiesLocal = properties;
-
-    Widget buildMenuitemChild(int? flexFactor) {
-      return Text(
-        'flex: $flexFactor',
-        style: flexFactor == propertiesLocal.flexFactor
-            ? theme.boldTextStyle.copyWith(color: emphasizedTextColor)
-            : theme.regularTextStyleWithColor(emphasizedTextColor),
-      );
-    }
-
-    DropdownMenuItem<int> buildMenuItem(int? flexFactor) {
-      return DropdownMenuItem(
-        value: flexFactor,
-        child: buildMenuitemChild(flexFactor),
-      );
-    }
-
-    return DropdownButton<int>(
-      value: propertiesLocal.flexFactor?.toInt().clamp(0, maximumFlexFactor),
-      onChanged: onChangeFlexFactor,
-      iconEnabledColor: textColor,
-      underline: buildUnderline(),
-      items: <DropdownMenuItem<int>>[
-        buildMenuItem(null),
-        for (var i = 0; i <= maximumFlexFactor; ++i) buildMenuItem(i),
-      ],
-    );
-  }
-
-  Widget _buildFlexFitChangerDropdown(ThemeData theme) {
-    Widget flexFitDescription(FlexFit flexFit) => Text(
-      'fit: ${flexFit.name}',
-      style: theme.regularTextStyleWithColor(emphasizedTextColor),
-    );
-
-    final propertiesLocal = properties;
-
-    // Disable FlexFit changer if widget is Expanded.
-    if (propertiesLocal.description == 'Expanded') {
-      return flexFitDescription(FlexFit.tight);
-    }
-
-    DropdownMenuItem<FlexFit> buildMenuItem(FlexFit flexFit) {
-      return DropdownMenuItem(
-        value: flexFit,
-        child: flexFitDescription(flexFit),
-      );
-    }
-
-    return DropdownButton<FlexFit>(
-      value: propertiesLocal.flexFit,
-      onChanged: onChangeFlexFit,
-      underline: buildUnderline(),
-      iconEnabledColor: emphasizedTextColor,
-      items: <DropdownMenuItem<FlexFit>>[
-        buildMenuItem(FlexFit.loose),
-        if (propertiesLocal.description != 'Expanded')
-          buildMenuItem(FlexFit.tight),
-      ],
-    );
-  }
-
-  Widget _buildContent(ThemeData theme) {
-    // TODO(https://github.com/flutter/devtools/issues/4058) allow more dynamic
-    // flex factor input
-    final currentFlexFactor = properties.flexFactor?.toInt() ?? 0;
-    final currentMaxFlexFactor = math.max(
-      currentFlexFactor,
-      maximumFlexFactorOptions,
-    );
-
-    return Container(
-      margin: const EdgeInsets.only(top: margin, left: margin),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.end,
-        children: [
-          Flexible(
-            child: _buildFlexFactorChangerDropdown(currentMaxFlexFactor, theme),
-          ),
-          if (!properties.hasFlexFactor)
-            Text(
-              'unconstrained ${root.isMainAxisHorizontal ? 'horizontal' : 'vertical'}',
-              style: theme.regularTextStyle.copyWith(
-                color: theme.colorScheme.unconstrainedColor,
-                fontStyle: FontStyle.italic,
-              ),
-              maxLines: 2,
-              softWrap: true,
-              overflow: TextOverflow.ellipsis,
-              textScaler: const TextScaler.linear(smallTextScaleFactor),
-              textAlign: TextAlign.center,
-            ),
-          _buildFlexFitChangerDropdown(theme),
-        ],
-      ),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final renderSize = renderProperties.size;
-    final renderOffset = renderProperties.offset;
-    final propertiesLocal = properties;
-    final rootLocal = root;
-
-    Widget buildEntranceAnimation(BuildContext _, Widget? child) {
-      final vertical = rootLocal.isMainAxisVertical;
-      final horizontal = rootLocal.isMainAxisHorizontal;
-
-      late Size size;
-      size = propertiesLocal.hasFlexFactor
-          ? SizeTween(
-              begin: Size(
-                horizontal ? minRenderWidth - entranceMargin : renderSize.width,
-                vertical ? minRenderHeight - entranceMargin : renderSize.height,
-              ),
-              end: renderSize,
-            ).evaluate(state.entranceCurve)!
-          : renderSize;
-      // Not-expanded widgets enter much faster.
-      return Opacity(
-        opacity: min([state.entranceCurve.value * 5, 1.0]),
-        child: Padding(
-          padding: EdgeInsets.symmetric(
-            horizontal: math.max(0.0, (renderSize.width - size.width) / 2),
-            vertical: math.max(0.0, (renderSize.height - size.height) / 2),
-          ),
-          child: child,
-        ),
-      );
-    }
-
-    return Positioned(
-      top: renderOffset.dy,
-      left: renderOffset.dx,
-      child: GestureDetector(
-        onTap: () => unawaited(state.onTap(propertiesLocal)),
-        onDoubleTap: () => state.onDoubleTap(propertiesLocal),
-        onLongPress: () => state.onDoubleTap(propertiesLocal),
-        child: SizedBox(
-          width: renderSize.width,
-          height: renderSize.height,
-          child: AnimatedBuilder(
-            animation: state.entranceController,
-            builder: buildEntranceAnimation,
-            child: WidgetVisualizer(
-              isSelected: isSelected,
-              layoutProperties: layoutProperties,
-              title: propertiesLocal.description ?? '',
-              overflowSide: propertiesLocal.overflowSide,
-              child: VisualizeWidthAndHeightWithConstraints(
-                arrowHeadSize: arrowHeadSize,
-                properties: propertiesLocal,
-                child: Align(
-                  alignment: Alignment.topRight,
-                  child: _buildContent(Theme.of(context)),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  /// define the number of flex factor to be shown in the flex dropdown button
-  /// for example if it's set to 5 the dropdown will consist of 6 items (null and 0..5)
-  static const maximumFlexFactorOptions = 5;
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart
deleted file mode 100644
index cc3b201..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/flex/utils.dart
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:ui';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-
-import '../../inspector_data_models.dart';
-import '../ui/utils.dart';
-
-String crossAxisAssetImageUrl(Axis direction, CrossAxisAlignment alignment) {
-  return 'assets/img/layout_explorer/cross_axis_alignment/'
-      '${direction.flexType.toLowerCase()}_${alignment.name}.png';
-}
-
-String mainAxisAssetImageUrl(Axis direction, MainAxisAlignment alignment) {
-  return 'assets/img/layout_explorer/main_axis_alignment/'
-      '${direction.flexType.toLowerCase()}_${alignment.name}.png';
-}
-
-class AnimatedFlexLayoutProperties
-    extends AnimatedLayoutProperties<FlexLayoutProperties>
-    implements FlexLayoutProperties {
-  AnimatedFlexLayoutProperties(super.begin, super.end, super.animation);
-
-  @override
-  CrossAxisAlignment? get crossAxisAlignment => end.crossAxisAlignment;
-
-  @override
-  MainAxisAlignment? get mainAxisAlignment => end.mainAxisAlignment;
-
-  @override
-  List<RenderProperties> childrenRenderProperties({
-    required double smallestRenderWidth,
-    required double largestRenderWidth,
-    required double smallestRenderHeight,
-    required double largestRenderHeight,
-    required double Function(Axis) maxSizeAvailable,
-  }) {
-    final beginRenderProperties = begin.childrenRenderProperties(
-      smallestRenderHeight: smallestRenderHeight,
-      smallestRenderWidth: smallestRenderWidth,
-      largestRenderHeight: largestRenderHeight,
-      largestRenderWidth: largestRenderWidth,
-      maxSizeAvailable: maxSizeAvailable,
-    );
-    final endRenderProperties = end.childrenRenderProperties(
-      smallestRenderHeight: smallestRenderHeight,
-      smallestRenderWidth: smallestRenderWidth,
-      largestRenderHeight: largestRenderHeight,
-      largestRenderWidth: largestRenderWidth,
-      maxSizeAvailable: maxSizeAvailable,
-    );
-    final result = <RenderProperties>[];
-    for (var i = 0; i < children.length; i++) {
-      final beginProps = beginRenderProperties[i];
-      final endProps = endRenderProperties[i];
-      final t = animation.value;
-      result.add(
-        RenderProperties(
-          axis: endProps.axis,
-          offset: Offset.lerp(beginProps.offset, endProps.offset, t),
-          size: Size.lerp(beginProps.size, endProps.size, t),
-          realSize: Size.lerp(beginProps.realSize, endProps.realSize, t),
-          layoutProperties: AnimatedLayoutProperties(
-            beginProps.layoutProperties,
-            endProps.layoutProperties,
-            animation,
-          ),
-        ),
-      );
-    }
-    // Add in the free space from the end.
-    // TODO(djshuckerow): We should make free space a part of
-    // RenderProperties so that we can animate between those.
-    result.addAll(endRenderProperties.where((prop) => prop.isFreeSpace));
-    return result;
-  }
-
-  @override
-  double get crossAxisDimension => lerpDouble(
-    begin.crossAxisDimension,
-    end.crossAxisDimension,
-    animation.value,
-  )!;
-
-  @override
-  Axis get crossAxisDirection => end.crossAxisDirection;
-
-  @override
-  List<RenderProperties> crossAxisSpaces({
-    required List<RenderProperties> childrenRenderProperties,
-    required double Function(Axis) maxSizeAvailable,
-  }) {
-    return end.crossAxisSpaces(
-      childrenRenderProperties: childrenRenderProperties,
-      maxSizeAvailable: maxSizeAvailable,
-    );
-  }
-
-  @override
-  Axis get direction => end.direction;
-
-  @override
-  String get horizontalDirectionDescription =>
-      end.horizontalDirectionDescription;
-
-  @override
-  bool get isMainAxisHorizontal => end.isMainAxisHorizontal;
-
-  @override
-  bool get isMainAxisVertical => end.isMainAxisVertical;
-
-  @override
-  double get mainAxisDimension => lerpDouble(
-    begin.mainAxisDimension,
-    end.mainAxisDimension,
-    animation.value,
-  )!;
-
-  @override
-  MainAxisSize? get mainAxisSize => end.mainAxisSize;
-
-  @override
-  TextBaseline? get textBaseline => end.textBaseline;
-
-  @override
-  TextDirection get textDirection => end.textDirection;
-
-  @override
-  double get totalFlex =>
-      lerpDouble(begin.totalFlex, end.totalFlex, animation.value)!;
-
-  @override
-  String get type => end.type;
-
-  @override
-  VerticalDirection get verticalDirection => end.verticalDirection;
-
-  @override
-  String get verticalDirectionDescription => end.verticalDirectionDescription;
-
-  /// Returns a frozen copy of these FlexLayoutProperties that does not animate.
-  ///
-  /// Useful for interrupting an animation with a transition to another [FlexLayoutProperties].
-  @override
-  FlexLayoutProperties copyWith({
-    Size? size,
-    List<LayoutProperties>? children,
-    BoxConstraints? constraints,
-    bool? isFlex,
-    String? description,
-    num? flexFactor,
-    FlexFit? flexFit,
-    Axis? direction,
-    MainAxisAlignment? mainAxisAlignment,
-    MainAxisSize? mainAxisSize,
-    CrossAxisAlignment? crossAxisAlignment,
-    TextDirection? textDirection,
-    VerticalDirection? verticalDirection,
-    TextBaseline? textBaseline,
-  }) {
-    return FlexLayoutProperties(
-      size: size ?? this.size,
-      children: children ?? this.children,
-      node: node,
-      constraints: constraints ?? this.constraints,
-      isFlex: isFlex ?? this.isFlex,
-      description: description ?? this.description,
-      flexFactor: flexFactor ?? this.flexFactor,
-      direction: direction ?? this.direction,
-      mainAxisAlignment: mainAxisAlignment ?? this.mainAxisAlignment,
-      mainAxisSize: mainAxisSize ?? this.mainAxisSize,
-      crossAxisAlignment: crossAxisAlignment ?? this.crossAxisAlignment,
-      textDirection: textDirection ?? this.textDirection,
-      verticalDirection: verticalDirection ?? this.verticalDirection,
-      textBaseline: textBaseline ?? this.textBaseline,
-    );
-  }
-
-  @override
-  bool get startIsTopLeft => end.startIsTopLeft;
-}
-
-/// LayoutProperties extension to be reused on LayoutProperties and AnimatedLayoutProperties
-
-extension AxisExtension on Axis {
-  String get flexType {
-    switch (this) {
-      case Axis.horizontal:
-        return 'Row';
-      case Axis.vertical:
-        return 'Column';
-    }
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/layout_explorer.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/layout_explorer.dart
deleted file mode 100644
index 116a3c6..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/layout_explorer.dart
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/widgets.dart';
-
-import '../../../shared/diagnostics/diagnostics_node.dart';
-import '../inspector_controller.dart';
-import '../layout_explorer/box/box.dart';
-import '../layout_explorer/flex/flex.dart';
-
-/// Tab that acts as a proxy to decide which widget to be displayed
-class LayoutExplorerTab extends StatefulWidget {
-  const LayoutExplorerTab({super.key, required this.controller});
-
-  final InspectorController controller;
-
-  @override
-  State<LayoutExplorerTab> createState() => _LayoutExplorerTabState();
-}
-
-class _LayoutExplorerTabState extends State<LayoutExplorerTab>
-    with AutomaticKeepAliveClientMixin<LayoutExplorerTab>, AutoDisposeMixin {
-  InspectorController get controller => widget.controller;
-
-  RemoteDiagnosticsNode? get selected =>
-      controller.selectedNode.value?.diagnostic;
-
-  RemoteDiagnosticsNode? previousSelection;
-
-  Widget rootWidget(RemoteDiagnosticsNode? node) {
-    if (node != null && FlexLayoutExplorerWidget.shouldDisplay(node)) {
-      return FlexLayoutExplorerWidget(controller);
-    }
-    if (node != null && BoxLayoutExplorerWidget.shouldDisplay(node)) {
-      return BoxLayoutExplorerWidget(controller);
-    }
-    return Center(
-      child: Text(
-        node != null
-            ? 'Currently, Layout Explorer only supports Box and Flex-based widgets.'
-            : 'Select a widget to view its layout.',
-        textAlign: TextAlign.center,
-        overflow: TextOverflow.clip,
-      ),
-    );
-  }
-
-  void onSelectionChanged() {
-    if (rootWidget(previousSelection).runtimeType !=
-        rootWidget(selected).runtimeType) {
-      setState(() => previousSelection = selected);
-    }
-  }
-
-  @override
-  void initState() {
-    super.initState();
-    addAutoDisposeListener(controller.selectedNode, onSelectionChanged);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    super.build(context);
-    return rootWidget(selected);
-  }
-
-  @override
-  bool get wantKeepAlive => true;
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart
deleted file mode 100644
index 7fcf002..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/arrow.dart
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:math';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-const defaultArrowColor = Colors.white;
-const defaultArrowStrokeWidth = 2.0;
-const defaultDistanceToArrow = 4.0;
-
-enum ArrowType { up, left, right, down }
-
-Axis axis(ArrowType type) => (type == ArrowType.up || type == ArrowType.down)
-    ? Axis.vertical
-    : Axis.horizontal;
-
-/// Widget that draws a bidirectional arrow around another widget.
-///
-/// This widget is typically used to help draw diagrams.
-@immutable
-class ArrowWrapper extends StatelessWidget {
-  ArrowWrapper.unidirectional({
-    super.key,
-    this.child,
-    required ArrowType type,
-    this.arrowColor = defaultArrowColor,
-    double? arrowHeadSize,
-    this.arrowStrokeWidth = defaultArrowStrokeWidth,
-    this.childMarginFromArrow = defaultDistanceToArrow,
-  }) : assert(childMarginFromArrow > 0.0),
-       direction = axis(type),
-       isBidirectional = false,
-       startArrowType = type,
-       endArrowType = type,
-       arrowHeadSize = arrowHeadSize ?? defaultIconSize;
-
-  const ArrowWrapper.bidirectional({
-    super.key,
-    this.child,
-    required this.direction,
-    this.arrowColor = defaultArrowColor,
-    required this.arrowHeadSize,
-    this.arrowStrokeWidth = defaultArrowStrokeWidth,
-    this.childMarginFromArrow = defaultDistanceToArrow,
-  }) : assert(arrowHeadSize >= 0.0),
-       assert(childMarginFromArrow >= 0.0),
-       isBidirectional = true,
-       startArrowType = direction == Axis.horizontal
-           ? ArrowType.left
-           : ArrowType.up,
-       endArrowType = direction == Axis.horizontal
-           ? ArrowType.right
-           : ArrowType.down;
-
-  final Color arrowColor;
-  final double arrowHeadSize;
-  final double arrowStrokeWidth;
-  final Widget? child;
-
-  final Axis direction;
-  final double childMarginFromArrow;
-
-  final bool isBidirectional;
-  final ArrowType startArrowType;
-  final ArrowType endArrowType;
-
-  double get verticalMarginFromArrow {
-    if (child == null || direction == Axis.horizontal) return 0.0;
-    return childMarginFromArrow;
-  }
-
-  double get horizontalMarginFromArrow {
-    if (child == null || direction == Axis.vertical) return 0.0;
-    return childMarginFromArrow;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Flex(
-      direction: direction,
-      children: <Widget>[
-        Expanded(
-          child: Container(
-            margin: EdgeInsets.only(
-              bottom: verticalMarginFromArrow,
-              right: horizontalMarginFromArrow,
-            ),
-            child: ArrowWidget(
-              color: arrowColor,
-              headSize: arrowHeadSize,
-              strokeWidth: arrowStrokeWidth,
-              type: startArrowType,
-              shouldDrawHead: isBidirectional
-                  ? true
-                  : (startArrowType == ArrowType.left ||
-                        startArrowType == ArrowType.up),
-            ),
-          ),
-        ),
-        if (child != null) child!,
-        Expanded(
-          child: Container(
-            margin: EdgeInsets.only(
-              top: verticalMarginFromArrow,
-              left: horizontalMarginFromArrow,
-            ),
-            child: ArrowWidget(
-              color: arrowColor,
-              headSize: arrowHeadSize,
-              strokeWidth: arrowStrokeWidth,
-              type: endArrowType,
-              shouldDrawHead: isBidirectional
-                  ? true
-                  : (endArrowType == ArrowType.right ||
-                        endArrowType == ArrowType.down),
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-}
-
-/// Widget that draws a fully sized, centered, unidirectional arrow according to its constraints
-@immutable
-class ArrowWidget extends StatelessWidget {
-  ArrowWidget({
-    this.color = defaultArrowColor,
-    required this.headSize,
-    super.key,
-    this.shouldDrawHead = true,
-    this.strokeWidth = defaultArrowStrokeWidth,
-    required this.type,
-  }) : assert(headSize > 0.0),
-       assert(strokeWidth > 0.0),
-       _painter = _ArrowPainter(
-         headSize: headSize,
-         color: color,
-         strokeWidth: strokeWidth,
-         type: type,
-         shouldDrawHead: shouldDrawHead,
-       );
-
-  final Color color;
-
-  /// The arrow head is a Equilateral triangle
-  final double headSize;
-
-  final double strokeWidth;
-
-  final ArrowType type;
-
-  final CustomPainter _painter;
-
-  final bool shouldDrawHead;
-
-  @override
-  Widget build(BuildContext context) {
-    return CustomPaint(painter: _painter, child: Container());
-  }
-}
-
-class _ArrowPainter extends CustomPainter {
-  _ArrowPainter({
-    required this.headSize,
-    this.strokeWidth = defaultArrowStrokeWidth,
-    this.color = defaultArrowColor,
-    this.shouldDrawHead = true,
-    required this.type,
-  }) : // the height of an equilateral triangle
-       headHeight = 0.5 * sqrt(3) * headSize;
-
-  final Color color;
-  final double headSize;
-  final bool shouldDrawHead;
-  final double strokeWidth;
-  final ArrowType type;
-
-  final double headHeight;
-
-  bool headIsGreaterThanConstraint(Size size) {
-    if (type == ArrowType.left || type == ArrowType.right) {
-      return headHeight >= (size.width);
-    }
-    return headHeight >= (size.height);
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) =>
-      !(oldDelegate is _ArrowPainter &&
-          headSize == oldDelegate.headSize &&
-          strokeWidth == oldDelegate.strokeWidth &&
-          color == oldDelegate.color &&
-          type == oldDelegate.type);
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    final paint = Paint()
-      ..color = color
-      ..strokeWidth = strokeWidth;
-
-    final originX = size.width / 2, originY = size.height / 2;
-    Offset lineStartingPoint = Offset.zero;
-    Offset lineEndingPoint = Offset.zero;
-
-    if (!headIsGreaterThanConstraint(size) && shouldDrawHead) {
-      Offset p1, p2, p3;
-      final headSizeDividedBy2 = headSize / 2;
-      switch (type) {
-        case ArrowType.up:
-          p1 = Offset(originX, 0);
-          p2 = Offset(originX - headSizeDividedBy2, headHeight);
-          p3 = Offset(originX + headSizeDividedBy2, headHeight);
-          break;
-        case ArrowType.left:
-          p1 = Offset(0, originY);
-          p2 = Offset(headHeight, originY - headSizeDividedBy2);
-          p3 = Offset(headHeight, originY + headSizeDividedBy2);
-          break;
-        case ArrowType.right:
-          final startingX = size.width - headHeight;
-          p1 = Offset(size.width, originY);
-          p2 = Offset(startingX, originY - headSizeDividedBy2);
-          p3 = Offset(startingX, originY + headSizeDividedBy2);
-          break;
-        case ArrowType.down:
-          final startingY = size.height - headHeight;
-          p1 = Offset(originX, size.height);
-          p2 = Offset(originX - headSizeDividedBy2, startingY);
-          p3 = Offset(originX + headSizeDividedBy2, startingY);
-          break;
-      }
-      final path = Path()
-        ..moveTo(p1.dx, p1.dy)
-        ..lineTo(p2.dx, p2.dy)
-        ..lineTo(p3.dx, p3.dy)
-        ..close();
-      canvas.drawPath(path, paint);
-
-      switch (type) {
-        case ArrowType.up:
-          lineStartingPoint = Offset(originX, headHeight);
-          lineEndingPoint = Offset(originX, size.height);
-          break;
-        case ArrowType.left:
-          lineStartingPoint = Offset(headHeight, originY);
-          lineEndingPoint = Offset(size.width, originY);
-          break;
-        case ArrowType.right:
-          final arrowHeadStartingX = size.width - headHeight;
-          lineStartingPoint = Offset(0, originY);
-          lineEndingPoint = Offset(arrowHeadStartingX, originY);
-          break;
-        case ArrowType.down:
-          final headStartingY = size.height - headHeight;
-          lineStartingPoint = Offset(originX, 0);
-          lineEndingPoint = Offset(originX, headStartingY);
-          break;
-      }
-    } else {
-      // draw full line
-      switch (type) {
-        case ArrowType.up:
-        case ArrowType.down:
-          lineStartingPoint = Offset(originX, 0);
-          lineEndingPoint = Offset(originX, size.height);
-          break;
-        case ArrowType.left:
-        case ArrowType.right:
-          lineStartingPoint = Offset(0, originY);
-          lineEndingPoint = Offset(size.width, originY);
-          break;
-      }
-    }
-    canvas.drawLine(lineStartingPoint, lineEndingPoint, paint);
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart
deleted file mode 100644
index cc5e40c..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/dimension.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:flutter/material.dart';
-
-import 'theme.dart';
-
-/// Text widget for displaying width / height.
-Widget dimensionDescription(
-  TextSpan description,
-  bool overflow,
-  ColorScheme colorScheme,
-) {
-  final text = Text.rich(
-    description,
-    textAlign: TextAlign.center,
-    style: overflow
-        ? overflowingDimensionIndicatorTextStyle(colorScheme)
-        : dimensionIndicatorTextStyle,
-    overflow: TextOverflow.ellipsis,
-  );
-  if (overflow) {
-    return Container(
-      padding: const EdgeInsets.symmetric(
-        vertical: minPadding,
-        horizontal: overflowTextHorizontalPadding,
-      ),
-      decoration: BoxDecoration(
-        color: colorScheme.overflowBackgroundColor,
-        borderRadius: BorderRadius.circular(4.0),
-      ),
-      child: Center(child: text),
-    );
-  }
-  return text;
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart
deleted file mode 100644
index d515ed5..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/free_space.dart
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../../../shared/primitives/utils.dart';
-import '../../inspector_data_models.dart';
-import 'arrow.dart';
-import 'dimension.dart';
-import 'theme.dart';
-
-class FreeSpaceVisualizerWidget extends StatelessWidget {
-  const FreeSpaceVisualizerWidget(this.renderProperties, {super.key});
-
-  final RenderProperties renderProperties;
-
-  @override
-  Widget build(BuildContext context) {
-    final colorScheme = Theme.of(context).colorScheme;
-    final heightDescription =
-        'h=${toStringAsFixed(renderProperties.realHeight)}';
-    final widthDescription = 'w=${toStringAsFixed(renderProperties.realWidth)}';
-    final showWidth =
-        renderProperties.realWidth != renderProperties.layoutProperties.width;
-    final widthWidget = Column(
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Flexible(
-          child: dimensionDescription(
-            TextSpan(text: widthDescription),
-            false,
-            colorScheme,
-          ),
-        ),
-        Container(
-          margin: const EdgeInsets.symmetric(vertical: arrowMargin),
-          child: const ArrowWrapper.bidirectional(
-            arrowColor: widthIndicatorColor,
-            direction: Axis.horizontal,
-            arrowHeadSize: arrowHeadSize,
-          ),
-        ),
-      ],
-    );
-    final heightWidget = SizedBox(
-      width: heightOnlyIndicatorSize,
-      child: Row(
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          Flexible(
-            child: dimensionDescription(
-              TextSpan(text: heightDescription),
-              false,
-              colorScheme,
-            ),
-          ),
-          Container(
-            margin: const EdgeInsets.symmetric(horizontal: arrowMargin),
-            child: const ArrowWrapper.bidirectional(
-              arrowColor: heightIndicatorColor,
-              direction: Axis.vertical,
-              arrowHeadSize: arrowHeadSize,
-              childMarginFromArrow: 0.0,
-            ),
-          ),
-        ],
-      ),
-    );
-    return Positioned(
-      top: renderProperties.offset.dy,
-      left: renderProperties.offset.dx,
-      child: SizedBox(
-        width: renderProperties.width,
-        height: renderProperties.height,
-        child: DevToolsTooltip(
-          message: '$widthDescription\n$heightDescription',
-          child: showWidth ? widthWidget : heightWidget,
-        ),
-      ),
-    );
-  }
-}
-
-class PaddingVisualizerWidget extends StatelessWidget {
-  const PaddingVisualizerWidget(
-    this.renderProperties, {
-    required this.horizontal,
-    super.key,
-  });
-
-  final RenderProperties renderProperties;
-  final bool horizontal;
-
-  @override
-  Widget build(BuildContext context) {
-    final colorScheme = Theme.of(context).colorScheme;
-    final heightDescription =
-        'h=${toStringAsFixed(renderProperties.realHeight)}';
-    final widthDescription = 'w=${toStringAsFixed(renderProperties.realWidth)}';
-    final widthWidget = Column(
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Flexible(
-          child: dimensionDescription(
-            TextSpan(text: widthDescription),
-            false,
-            colorScheme,
-          ),
-        ),
-        Container(
-          margin: const EdgeInsets.symmetric(vertical: arrowMargin),
-          child: const ArrowWrapper.bidirectional(
-            arrowColor: widthIndicatorColor,
-            direction: Axis.horizontal,
-            arrowHeadSize: arrowHeadSize,
-          ),
-        ),
-      ],
-    );
-    final heightWidget = SizedBox(
-      width: heightOnlyIndicatorSize,
-      child: Row(
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          Flexible(
-            child: dimensionDescription(
-              TextSpan(text: heightDescription),
-              false,
-              colorScheme,
-            ),
-          ),
-          Container(
-            margin: const EdgeInsets.symmetric(horizontal: arrowMargin),
-            child: const ArrowWrapper.bidirectional(
-              arrowColor: heightIndicatorColor,
-              direction: Axis.vertical,
-              arrowHeadSize: arrowHeadSize,
-              childMarginFromArrow: 0.0,
-            ),
-          ),
-        ],
-      ),
-    );
-    return Positioned(
-      top: renderProperties.offset.dy,
-      left: renderProperties.offset.dx,
-      child: SizedBox(
-        width: safePositiveDouble(renderProperties.width),
-        height: safePositiveDouble(renderProperties.height),
-        child: horizontal ? widthWidget : heightWidget,
-      ),
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart
deleted file mode 100644
index ac4229c..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/layout_explorer_widget.dart
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-
-import '../../../../shared/diagnostics/diagnostics_node.dart';
-import '../../../../shared/diagnostics/inspector_service.dart';
-import '../../../../shared/globals.dart';
-import '../../../../shared/primitives/utils.dart';
-import '../../inspector_controller.dart';
-import '../../inspector_data_models.dart';
-import 'utils.dart';
-
-const maxRequestsPerSecond = 3.0;
-
-/// Base class for layout widgets for all widget types.
-abstract class LayoutExplorerWidget extends StatefulWidget {
-  const LayoutExplorerWidget(this.inspectorController, {super.key});
-
-  final InspectorController inspectorController;
-}
-
-/// Base class for state objects for layout widgets for all widget types.
-abstract class LayoutExplorerWidgetState<
-  W extends LayoutExplorerWidget,
-  L extends LayoutProperties
->
-    extends State<W>
-    with TickerProviderStateMixin
-    implements InspectorServiceClient {
-  LayoutExplorerWidgetState() {
-    _onSelectionChangedCallback = onSelectionChanged;
-  }
-
-  late AnimationController entranceController;
-  late CurvedAnimation entranceCurve;
-  late AnimationController changeController;
-
-  late CurvedAnimation changeAnimation;
-
-  L? _previousProperties;
-
-  L? _properties;
-
-  InspectorObjectGroupManager? objectGroupManager;
-
-  AnimatedLayoutProperties<L>? get animatedProperties => _animatedProperties;
-  AnimatedLayoutProperties<L>? _animatedProperties;
-
-  L? get properties =>
-      _previousProperties ?? _animatedProperties as L? ?? _properties;
-
-  RemoteDiagnosticsNode? get selectedNode =>
-      inspectorController.selectedNode.value?.diagnostic;
-
-  InspectorController get inspectorController => widget.inspectorController;
-
-  InspectorService? get inspectorService =>
-      serviceConnection.inspectorService as InspectorService?;
-
-  late RateLimiter rateLimiter;
-
-  late Future<void> Function() _onSelectionChangedCallback;
-
-  Future<void> onSelectionChanged() async {
-    if (!mounted) return;
-    final selectedNodeLocal = selectedNode;
-    if (selectedNodeLocal == null) return;
-    if (!shouldDisplay(selectedNodeLocal)) return;
-    final prevRootId = id(_properties?.node);
-    final newRootId = id(getRoot(selectedNodeLocal));
-    final shouldFetch = prevRootId != newRootId;
-    if (shouldFetch) {
-      _dirty = false;
-      final newSelection = await fetchLayoutProperties();
-      _setProperties(newSelection);
-    } else {
-      updateHighlighted(_properties);
-    }
-  }
-
-  /// Whether this layout explorer can work with this kind of node.
-  bool shouldDisplay(RemoteDiagnosticsNode node);
-
-  List<LayoutProperties> get children => properties!.displayChildren;
-
-  LayoutProperties? highlighted;
-
-  /// Returns the root widget to show.
-  ///
-  /// For cases such as Flex widgets or in the future ListView widgets we may
-  /// want to show the layout for all widgets under a root that is the parent
-  /// of the current widget.
-  RemoteDiagnosticsNode? getRoot(RemoteDiagnosticsNode? node);
-
-  Future<L?> fetchLayoutProperties() async {
-    objectGroupManager?.cancelNext();
-    final manager = objectGroupManager!;
-    final nextObjectGroup = manager.next;
-    final node = await nextObjectGroup.getLayoutExplorerNode(
-      getRoot(selectedNode),
-    );
-    if (node == null || node.renderObject == null) return null;
-
-    if (!nextObjectGroup.disposed) {
-      assert(manager.next == nextObjectGroup);
-      manager.promoteNext();
-    }
-    return computeLayoutProperties(node);
-  }
-
-  L computeLayoutProperties(RemoteDiagnosticsNode node);
-
-  AnimatedLayoutProperties<L> computeAnimatedProperties(L nextProperties);
-
-  void updateHighlighted(L? newProperties);
-
-  String? id(RemoteDiagnosticsNode? node) => node?.valueRef.id;
-
-  void _registerInspectorControllerService() {
-    inspectorController.selectedNode.addListener(_onSelectionChangedCallback);
-    inspectorService?.addClient(this);
-  }
-
-  void _unregisterInspectorControllerService() {
-    inspectorController.selectedNode.removeListener(
-      _onSelectionChangedCallback,
-    );
-    inspectorService?.removeClient(this);
-  }
-
-  @override
-  void initState() {
-    super.initState();
-    rateLimiter = RateLimiter(maxRequestsPerSecond, refresh);
-    _registerInspectorControllerService();
-    _initAnimationStates();
-    _updateObjectGroupManager();
-    // TODO(jacobr): put inspector controller in Controllers and
-    // update on didChangeDependencies.
-    _animateProperties();
-  }
-
-  @override
-  void didUpdateWidget(W oldWidget) {
-    super.didUpdateWidget(oldWidget);
-    _updateObjectGroupManager();
-    _animateProperties();
-    if (oldWidget.inspectorController != inspectorController) {
-      _unregisterInspectorControllerService();
-      _registerInspectorControllerService();
-    }
-  }
-
-  @override
-  void dispose() {
-    entranceController.dispose();
-    changeController.dispose();
-    _unregisterInspectorControllerService();
-    super.dispose();
-  }
-
-  void _animateProperties() {
-    if (_animatedProperties != null) {
-      unawaited(changeController.forward());
-    }
-    if (_previousProperties != null) {
-      unawaited(entranceController.reverse());
-    } else {
-      unawaited(entranceController.forward());
-    }
-  }
-
-  // update selected widget in the device without triggering selection listener event.
-  // this is required so that we don't change focus
-  //   when tapping on a child is also Flex-based widget.
-  Future<void> setSelectionInspector(RemoteDiagnosticsNode node) async {
-    final service = node.objectGroupApi;
-    if (service != null && service is ObjectGroup) {
-      await service.setSelectionInspector(node.valueRef, false);
-    }
-  }
-
-  // update selected widget and trigger selection listener event to change focus.
-  void refreshSelection(RemoteDiagnosticsNode node) {
-    inspectorController.refreshSelection(node, node, true);
-  }
-
-  Future<void> onTap(LayoutProperties properties) async {
-    setState(() => highlighted = properties);
-    await setSelectionInspector(properties.node);
-  }
-
-  void onDoubleTap(LayoutProperties properties) {
-    refreshSelection(properties.node);
-  }
-
-  Future<void> refresh() async {
-    if (!_dirty) return;
-    _dirty = false;
-    final updatedProperties = await fetchLayoutProperties();
-    if (updatedProperties != null) {
-      _changeProperties(updatedProperties);
-    }
-  }
-
-  void _changeProperties(L nextProperties) {
-    if (!mounted) return;
-    updateHighlighted(nextProperties);
-    setState(() {
-      _animatedProperties = computeAnimatedProperties(nextProperties);
-      unawaited(changeController.forward(from: 0.0));
-    });
-  }
-
-  void _setProperties(L? newProperties) {
-    if (!mounted) return;
-    updateHighlighted(newProperties);
-    if (_properties == newProperties) {
-      return;
-    }
-    setState(() {
-      _previousProperties ??= _properties;
-      _properties = newProperties;
-    });
-    _animateProperties();
-  }
-
-  void _initAnimationStates() {
-    entranceController = longAnimationController(this)
-      ..addStatusListener((status) {
-        if (status == AnimationStatus.dismissed) {
-          setState(() {
-            _previousProperties = null;
-            unawaited(entranceController.forward());
-          });
-        }
-      });
-    entranceCurve = defaultCurvedAnimation(entranceController);
-    changeController = longAnimationController(this)
-      ..addStatusListener((status) {
-        if (status == AnimationStatus.completed) {
-          setState(() {
-            _properties = _animatedProperties!.end;
-            _animatedProperties = null;
-            changeController.value = 0.0;
-          });
-        }
-      });
-    changeAnimation = defaultCurvedAnimation(changeController);
-  }
-
-  void _updateObjectGroupManager() {
-    final service = serviceConnection.inspectorService;
-    if (service != objectGroupManager?.inspectorService) {
-      objectGroupManager = InspectorObjectGroupManager(
-        service as InspectorService,
-        'flex-layout',
-      );
-    }
-    unawaited(onSelectionChanged());
-  }
-
-  bool _dirty = false;
-
-  @override
-  void onFlutterFrame() {
-    if (!mounted) return;
-    if (_dirty) {
-      rateLimiter.scheduleRequest();
-    }
-  }
-
-  // TODO(albertusangga): Investigate why onForceRefresh is not getting called.
-  @override
-  Future<void> onForceRefresh() async {
-    final properties = await fetchLayoutProperties();
-    if (properties != null) {
-      _setProperties(properties);
-    }
-  }
-
-  /// Currently this is not working so we should listen to controller selection event instead.
-  @override
-  Future<void> onInspectorSelectionChanged() async {}
-
-  /// Register callback to be executed once Flutter frame is ready.
-  void markAsDirty() {
-    _dirty = true;
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/overflow_indicator_painter.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/overflow_indicator_painter.dart
deleted file mode 100644
index 298b778..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/overflow_indicator_painter.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:ui' as ui;
-
-import 'package:flutter/rendering.dart';
-
-import '../../inspector_data_models.dart';
-
-/// CustomPainter for drawing [DebugOverflowIndicatorMixin]'s patterned background.
-/// Draws overflow pattern on the [OverflowSide] of the widget.
-///
-/// [DebugOverflowIndicatorMixin] can not be reused here
-/// because it is a mixin on RenderObject and requires real overflows on the widget.
-///
-/// If [side] is set to [OverflowSide.right],
-/// the pattern will occupy the whole height
-/// and the width will be the given [size].
-///
-/// If [side] is set to [OverflowSide.bottom],
-/// the pattern will occupy the whole width
-/// and the height will be the given [size].
-///
-/// See also:
-/// * [DebugOverflowIndicatorMixin]
-class OverflowIndicatorPainter extends CustomPainter {
-  const OverflowIndicatorPainter(this.side, this.size);
-
-  final OverflowSide side;
-  final double size;
-
-  /// These static variables  are taken from [DebugOverflowIndicatorMixin]
-  /// since all of them are private.
-  static const black = Color(0xBF000000);
-  static const yellow = Color(0xBFFFFF00);
-  static final indicatorPaint = Paint()
-    ..shader = ui.Gradient.linear(
-      const Offset(0.0, 0.0),
-      const Offset(10.0, 10.0),
-      <Color>[black, yellow, yellow, black],
-      <double>[0.25, 0.25, 0.75, 0.75],
-      TileMode.repeated,
-    );
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    final bottomOverflow = OverflowSide.bottom == side;
-    final width = bottomOverflow ? size.width : this.size;
-    final height = !bottomOverflow ? size.height : this.size;
-
-    final left = bottomOverflow ? 0.0 : size.width - width;
-    final top = side == OverflowSide.right ? 0.0 : size.height - height;
-    final rect = Rect.fromLTWH(left, top, width, height);
-    canvas.drawRect(rect, indicatorPaint);
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) {
-    return oldDelegate is OverflowIndicatorPainter &&
-        (side != oldDelegate.side || size != oldDelegate.size);
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart
deleted file mode 100644
index 974a0a5..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-const margin = 6.0;
-
-const arrowHeadSize = 8.0;
-const arrowMargin = 4.0;
-const arrowStrokeWidth = 1.5;
-
-/// Hardcoded sizes for scaling the flex children widget properly.
-const minRenderWidth = 250.0;
-const minRenderHeight = 250.0;
-
-const minPadding = 2.0;
-const overflowTextHorizontalPadding = 8.0;
-
-/// The size to shrink a widget by when animating it in.
-const entranceMargin = 50.0;
-
-const defaultMaxRenderWidth = 400.0;
-const defaultMaxRenderHeight = 400.0;
-
-const widgetTitleMaxWidthPercentage = 0.75;
-
-/// Hardcoded arrow size respective to its cross axis (because it's unconstrained).
-const heightAndConstraintIndicatorSize = 48.0;
-const widthAndConstraintIndicatorSize = 56.0;
-const mainAxisArrowIndicatorSize = 48.0;
-const crossAxisArrowIndicatorSize = 48.0;
-
-const heightOnlyIndicatorSize = 72.0;
-
-/// Minimum size to display width/height inside the arrow
-const minWidthToDisplayWidthInsideArrow = 200.0;
-const minHeightToDisplayHeightInsideArrow = 200.0;
-
-const smallTextScaleFactor = 0.8;
-
-/// Height for limiting asset image (selected one in the drop down).
-const axisAlignmentAssetImageHeight = 24.0;
-
-const minHeightToAllowTruncating = 375.0;
-const minWidthToAllowTruncating = 375.0;
-
-// Story of Layout colors
-const mainAxisLightColor = Color(0xff2c5daa);
-const mainAxisDarkColor = Color(0xff2c5daa);
-
-const textColor = Color(0xff55767f);
-const emphasizedTextColor = Color(0xff009aca);
-
-const crossAxisLightColor = Color(0xff8ac652);
-const crossAxisDarkColor = Color(0xff8ac652);
-
-const mainAxisTextColorLight = Color(0xFF1375bc);
-const mainAxisTextColorDark = Color(0xFF1375bc);
-
-const crossAxisTextColorLight = Color(0xFF66672C);
-const crossAxisTextColorsDark = Color(0xFFB3D25A);
-
-const overflowBackgroundColorDark = Color(0xFFB00020);
-const overflowBackgroundColorLight = Color(0xFFB00020);
-
-const overflowTextColorDark = Color(0xfff5846b);
-const overflowTextColorLight = Color(0xffdea089);
-
-const backgroundColorSelectedDark = Color(
-  0x4d474747,
-); // TODO(jacobr): we would like Color(0x4dedeeef) but that makes the background show through.
-const backgroundColorSelectedLight = Color(0x4dedeeef);
-
-extension LayoutExplorerColorScheme on ColorScheme {
-  Color get mainAxisColor => isLight ? mainAxisLightColor : mainAxisDarkColor;
-
-  Color get widgetNameColor => isLight ? Colors.white : Colors.black;
-
-  Color get crossAxisColor =>
-      isLight ? crossAxisLightColor : crossAxisDarkColor;
-
-  Color get mainAxisTextColor =>
-      isLight ? mainAxisTextColorLight : mainAxisTextColorDark;
-
-  Color get crossAxisTextColor =>
-      isLight ? crossAxisTextColorLight : crossAxisTextColorsDark;
-
-  Color get overflowBackgroundColor =>
-      isLight ? overflowBackgroundColorLight : overflowBackgroundColorDark;
-
-  Color get overflowTextColor =>
-      isLight ? overflowTextColorLight : overflowTextColorDark;
-
-  Color get backgroundColorSelected =>
-      isLight ? backgroundColorSelectedLight : backgroundColorSelectedDark;
-
-  Color get unconstrainedColor =>
-      isLight ? unconstrainedLightColor : unconstrainedDarkColor;
-}
-
-const backgroundColorDark = Color(0xff30302f);
-const backgroundColorLight = Color(0xffffffff);
-
-const unconstrainedDarkColor = Color(0xffdea089);
-const unconstrainedLightColor = Color(0xfff5846b);
-
-const widthIndicatorColor = textColor;
-const heightIndicatorColor = textColor;
-
-const negativeSpaceDarkAssetName =
-    'assets/img/layout_explorer/negative_space_dark.png';
-const negativeSpaceLightAssetName =
-    'assets/img/layout_explorer/negative_space_light.png';
-
-const dimensionIndicatorTextStyle = TextStyle(
-  height: 1.0,
-  letterSpacing: 1.1,
-  color: emphasizedTextColor,
-  fontSize: defaultFontSize,
-);
-
-TextStyle overflowingDimensionIndicatorTextStyle(ColorScheme colorScheme) =>
-    dimensionIndicatorTextStyle.merge(
-      TextStyle(
-        fontWeight: FontWeight.bold,
-        color: colorScheme.overflowTextColor,
-      ),
-    );
-
-Widget buildUnderline() {
-  return Container(
-    height: 1.0,
-    decoration: const BoxDecoration(
-      border: Border(bottom: BorderSide(color: textColor, width: 0.0)),
-    ),
-  );
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart
deleted file mode 100644
index 798ea7a..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/utils.dart
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:ui';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../../../shared/diagnostics/diagnostics_node.dart';
-import '../../../../shared/primitives/utils.dart';
-import '../../inspector_data_models.dart';
-import 'overflow_indicator_painter.dart';
-import 'theme.dart';
-import 'widgets_theme.dart';
-
-/// A widget for positioning sized widgets that follows layout as follows:
-///      | top    |
-/// left | center | right
-///      | bottom |
-@immutable
-class BorderLayout extends StatelessWidget {
-  const BorderLayout({
-    super.key,
-    this.left,
-    this.leftWidth,
-    this.top,
-    this.topHeight,
-    this.right,
-    this.rightWidth,
-    this.bottom,
-    this.bottomHeight,
-    this.center,
-  }) : assert(
-         left != null ||
-             top != null ||
-             right != null ||
-             bottom != null ||
-             center != null,
-       );
-
-  final Widget? center;
-  final Widget? top;
-  final Widget? left;
-  final Widget? right;
-  final Widget? bottom;
-
-  final double? leftWidth;
-  final double? rightWidth;
-  final double? topHeight;
-  final double? bottomHeight;
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: <Widget>[
-        Center(
-          child: Container(
-            margin: EdgeInsets.only(
-              left: leftWidth ?? 0,
-              right: rightWidth ?? 0,
-              top: topHeight ?? 0,
-              bottom: bottomHeight ?? 0,
-            ),
-            child: center,
-          ),
-        ),
-        if (top != null)
-          Align(
-            alignment: Alignment.topCenter,
-            child: SizedBox(height: topHeight, child: top),
-          ),
-        if (left != null)
-          Align(
-            alignment: Alignment.centerLeft,
-            child: SizedBox(width: leftWidth, child: left),
-          ),
-        if (right != null)
-          Align(
-            alignment: Alignment.centerRight,
-            child: SizedBox(width: rightWidth, child: right),
-          ),
-        if (bottom != null)
-          Align(
-            alignment: Alignment.bottomCenter,
-            child: SizedBox(height: bottomHeight, child: bottom),
-          ),
-      ],
-    );
-  }
-}
-
-@immutable
-class Truncateable extends StatelessWidget {
-  const Truncateable({super.key, this.truncate = false, required this.child});
-
-  final Widget child;
-  final bool truncate;
-
-  @override
-  Widget build(BuildContext context) {
-    return Flexible(flex: truncate ? 1 : 0, child: child);
-  }
-}
-
-/// Widget that draws bounding box with the title (usually widget name) in its
-/// top left.
-///
-/// * [hint] is an optional widget to be placed in the top right of the box.
-/// * [child] is an optional widget to be placed in the center of the box.
-class WidgetVisualizer extends StatelessWidget {
-  const WidgetVisualizer({
-    super.key,
-    required this.title,
-    this.hint,
-    required this.isSelected,
-    required this.layoutProperties,
-    required this.child,
-    this.overflowSide,
-    this.largeTitle = false,
-  });
-
-  final LayoutProperties layoutProperties;
-  final String title;
-  final Widget child;
-  final Widget? hint;
-  final bool isSelected;
-  final bool largeTitle;
-
-  final OverflowSide? overflowSide;
-
-  static const _overflowIndicatorSize = 20.0;
-  static const _borderUnselectedWidth = 1.0;
-  static const _borderSelectedWidth = 3.0;
-  static const _selectedPadding = 4.0;
-
-  bool get drawOverflow => overflowSide != null;
-
-  @override
-  Widget build(BuildContext context) {
-    final theme = Theme.of(context);
-    final colorScheme = theme.colorScheme;
-    final properties = layoutProperties;
-    final borderColor = WidgetTheme.fromName(properties.node.description).color;
-    final boxAdjust = isSelected ? _selectedPadding : 0.0;
-
-    return LayoutBuilder(
-      builder: (context, constraints) {
-        final hintLocal = hint;
-        return OverflowBox(
-          minWidth: constraints.minWidth + boxAdjust,
-          maxWidth: constraints.maxWidth + boxAdjust,
-          maxHeight: constraints.maxHeight + boxAdjust,
-          minHeight: constraints.minHeight + boxAdjust,
-          child: Container(
-            decoration: BoxDecoration(
-              border: Border.all(
-                color: borderColor,
-                width: isSelected
-                    ? _borderSelectedWidth
-                    : _borderUnselectedWidth,
-              ),
-              color: isSelected
-                  ? theme.canvasColor.brighten()
-                  : theme.canvasColor.darken(),
-              boxShadow: isSelected
-                  ? [
-                      BoxShadow(
-                        color: Colors.black.withAlpha(255 ~/ 2),
-                        blurRadius: 20,
-                      ),
-                    ]
-                  : null,
-            ),
-            child: Stack(
-              children: [
-                if (drawOverflow)
-                  Positioned.fill(
-                    child: CustomPaint(
-                      painter: OverflowIndicatorPainter(
-                        overflowSide!,
-                        _overflowIndicatorSize,
-                      ),
-                    ),
-                  ),
-                Container(
-                  margin: EdgeInsets.only(
-                    right: overflowSide == OverflowSide.right
-                        ? _overflowIndicatorSize
-                        : 0.0,
-                    bottom: overflowSide == OverflowSide.bottom
-                        ? _overflowIndicatorSize
-                        : 0.0,
-                  ),
-                  child: Column(
-                    crossAxisAlignment: CrossAxisAlignment.stretch,
-                    mainAxisSize: MainAxisSize.min,
-                    children: [
-                      IntrinsicHeight(
-                        child: Row(
-                          crossAxisAlignment: CrossAxisAlignment.stretch,
-                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                          children: [
-                            Flexible(
-                              child: Container(
-                                constraints: BoxConstraints(
-                                  maxWidth: largeTitle
-                                      ? defaultMaxRenderWidth
-                                      : minRenderWidth *
-                                            widgetTitleMaxWidthPercentage,
-                                ),
-                                decoration: BoxDecoration(color: borderColor),
-                                padding: const EdgeInsets.all(4.0),
-                                child: Center(
-                                  child: Text(
-                                    title,
-                                    style: theme.regularTextStyleWithColor(
-                                      colorScheme.widgetNameColor,
-                                    ),
-                                    overflow: TextOverflow.ellipsis,
-                                  ),
-                                ),
-                              ),
-                            ),
-                            if (hintLocal != null) Flexible(child: hintLocal),
-                          ],
-                        ),
-                      ),
-                      Expanded(child: child),
-                    ],
-                  ),
-                ),
-              ],
-            ),
-          ),
-        );
-      },
-    );
-  }
-}
-
-class AnimatedLayoutProperties<T extends LayoutProperties>
-    implements LayoutProperties {
-  AnimatedLayoutProperties(this.begin, this.end, this.animation)
-    : assert(begin.children.length == end.children.length),
-      _children = [
-        for (var i = 0; i < begin.children.length; i++)
-          AnimatedLayoutProperties(
-            begin.children[i],
-            end.children[i],
-            animation,
-          ),
-      ];
-
-  final T begin;
-  final T end;
-  final Animation<double> animation;
-  final List<LayoutProperties> _children;
-
-  @override
-  LayoutProperties? get parent => end.parent;
-
-  @override
-  set parent(LayoutProperties? parent) {
-    end.parent = parent;
-  }
-
-  @override
-  List<LayoutProperties> get children {
-    return _children;
-  }
-
-  List<double> _lerpList(List<double> l1, List<double> l2) {
-    assert(l1.length == l2.length);
-    if (l1.isEmpty) return [];
-    final animationLocal = animation;
-    return [
-      for (var i = 0; i < children.length; i++)
-        lerpDouble(l1[i], l2[i], animationLocal.value)!,
-    ];
-  }
-
-  @override
-  List<double> childrenDimensions(Axis axis) {
-    final beginDimensions = begin.childrenDimensions(axis);
-    final endDimensions = end.childrenDimensions(axis);
-    return _lerpList(beginDimensions, endDimensions);
-  }
-
-  @override
-  List<double> get childrenHeights =>
-      _lerpList(begin.childrenHeights, end.childrenHeights);
-
-  @override
-  List<double> get childrenWidths =>
-      _lerpList(begin.childrenWidths, end.childrenWidths);
-
-  @override
-  BoxConstraints? get constraints {
-    try {
-      return BoxConstraints.lerp(
-        begin.constraints,
-        end.constraints,
-        animation.value,
-      );
-    } catch (e) {
-      return end.constraints;
-    }
-  }
-
-  @override
-  String describeWidthConstraints() {
-    final constraintsLocal = constraints!;
-    return constraintsLocal.hasBoundedWidth
-        ? LayoutProperties.describeAxis(
-            constraintsLocal.minWidth,
-            constraintsLocal.maxWidth,
-            'w',
-          )
-        : 'w=unconstrained';
-  }
-
-  @override
-  String describeHeightConstraints() {
-    final constraintsLocal = constraints!;
-    return constraintsLocal.hasBoundedHeight
-        ? LayoutProperties.describeAxis(
-            constraintsLocal.minHeight,
-            constraintsLocal.maxHeight,
-            'h',
-          )
-        : 'h=unconstrained';
-  }
-
-  @override
-  String describeWidth() => 'w=${toStringAsFixed(size.width)}';
-
-  @override
-  String describeHeight() => 'h=${toStringAsFixed(size.height)}';
-
-  @override
-  String? get description => end.description;
-
-  @override
-  double dimension(Axis axis) {
-    return lerpDouble(
-      begin.dimension(axis),
-      end.dimension(axis),
-      animation.value,
-    )!;
-  }
-
-  @override
-  num? get flexFactor =>
-      lerpDouble(begin.flexFactor, end.flexFactor, animation.value);
-
-  @override
-  bool get hasChildren => children.isNotEmpty;
-
-  @override
-  double get height => size.height;
-
-  @override
-  bool get isFlex => begin.isFlex && end.isFlex;
-
-  @override
-  RemoteDiagnosticsNode get node => end.node;
-
-  @override
-  Size get size {
-    return Size.lerp(begin.size, end.size, animation.value)!;
-  }
-
-  @override
-  int get totalChildren => end.totalChildren;
-
-  @override
-  double get width => size.width;
-
-  @override
-  bool get hasFlexFactor => begin.hasFlexFactor && end.hasFlexFactor;
-
-  @override
-  LayoutProperties copyWith({
-    List<LayoutProperties>? children,
-    BoxConstraints? constraints,
-    String? description,
-    int? flexFactor,
-    FlexFit? flexFit,
-    bool? isFlex,
-    Size? size,
-  }) {
-    return LayoutProperties.values(
-      node: node,
-      children: children ?? this.children,
-      constraints: constraints ?? this.constraints,
-      description: description ?? this.description,
-      flexFactor: flexFactor ?? this.flexFactor,
-      flexFit: flexFit ?? this.flexFit,
-      isFlex: isFlex ?? this.isFlex,
-      size: size ?? this.size,
-    );
-  }
-
-  @override
-  bool get isOverflowWidth => end.isOverflowWidth;
-
-  @override
-  bool get isOverflowHeight => end.isOverflowHeight;
-
-  @override
-  FlexFit? get flexFit => end.flexFit;
-
-  @override
-  List<LayoutProperties> get displayChildren => end.displayChildren;
-}
-
-class LayoutExplorerBackground extends StatelessWidget {
-  const LayoutExplorerBackground({super.key, required this.colorScheme});
-
-  final ColorScheme colorScheme;
-
-  @override
-  Widget build(BuildContext context) {
-    return Positioned.fill(
-      child: Opacity(
-        opacity: colorScheme.isLight ? 0.3 : 0.2,
-        child: Image.asset(
-          colorScheme.isLight
-              ? negativeSpaceLightAssetName
-              : negativeSpaceDarkAssetName,
-          fit: BoxFit.none,
-          repeat: ImageRepeat.repeat,
-          alignment: Alignment.topLeft,
-        ),
-      ),
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart
deleted file mode 100644
index 45de404..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widget_constraints.dart
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:flutter/material.dart';
-
-import '../../../../shared/primitives/math_utils.dart';
-import '../../../../shared/primitives/utils.dart';
-import '../../inspector_data_models.dart';
-import 'arrow.dart';
-import 'dimension.dart';
-import 'theme.dart';
-import 'utils.dart';
-
-class VisualizeWidthAndHeightWithConstraints extends StatelessWidget {
-  const VisualizeWidthAndHeightWithConstraints({
-    super.key,
-    required this.properties,
-    double? arrowHeadSize,
-    required this.child,
-    this.warnIfUnconstrained = true,
-  }) : arrowHeadSize = arrowHeadSize ?? defaultIconSize;
-
-  final Widget child;
-  final LayoutProperties properties;
-  final double arrowHeadSize;
-  final bool warnIfUnconstrained;
-
-  @override
-  Widget build(BuildContext context) {
-    final propertiesLocal = properties;
-    final showChildrenWidthsSum =
-        propertiesLocal is FlexLayoutProperties &&
-        propertiesLocal.isOverflowWidth;
-    const bottomHeight = widthAndConstraintIndicatorSize;
-    const rightWidth = heightAndConstraintIndicatorSize;
-    final colorScheme = Theme.of(context).colorScheme;
-
-    final showOverflowHeight =
-        properties is FlexLayoutProperties && propertiesLocal.isOverflowHeight;
-    final heightDescription = RotatedBox(
-      quarterTurns: 1,
-      child: dimensionDescription(
-        TextSpan(
-          children: [
-            TextSpan(text: propertiesLocal.describeHeight()),
-            if (propertiesLocal.constraints != null) ...[
-              if (!showOverflowHeight) const TextSpan(text: '\n'),
-              TextSpan(
-                text: ' (${propertiesLocal.describeHeightConstraints()})',
-                style:
-                    propertiesLocal.constraints!.hasBoundedHeight ||
-                        !warnIfUnconstrained
-                    ? null
-                    : TextStyle(color: colorScheme.unconstrainedColor),
-              ),
-            ],
-            if (showOverflowHeight)
-              TextSpan(
-                text:
-                    '\nchildren take: '
-                    '${toStringAsFixed(sum(propertiesLocal.childrenHeights))}',
-              ),
-          ],
-        ),
-        propertiesLocal.isOverflowHeight,
-        colorScheme,
-      ),
-    );
-    final right = Container(
-      margin: const EdgeInsets.only(
-        top: margin,
-        left: margin,
-        bottom: bottomHeight,
-        right: minPadding, // custom margin for not sticking to the corner
-      ),
-      child: LayoutBuilder(
-        builder: (context, constraints) {
-          final displayHeightOutsideArrow =
-              constraints.maxHeight < minHeightToDisplayHeightInsideArrow;
-          return Row(
-            children: [
-              Truncateable(
-                truncate: !displayHeightOutsideArrow,
-                child: Container(
-                  margin: const EdgeInsets.symmetric(horizontal: arrowMargin),
-                  child: ArrowWrapper.bidirectional(
-                    arrowColor: heightIndicatorColor,
-                    arrowStrokeWidth: arrowStrokeWidth,
-                    arrowHeadSize: arrowHeadSize,
-                    direction: Axis.vertical,
-                    child: displayHeightOutsideArrow ? null : heightDescription,
-                  ),
-                ),
-              ),
-              if (displayHeightOutsideArrow) Flexible(child: heightDescription),
-            ],
-          );
-        },
-      ),
-    );
-
-    final widthDescription = dimensionDescription(
-      TextSpan(
-        children: [
-          TextSpan(text: '${propertiesLocal.describeWidth()}; '),
-          if (propertiesLocal.constraints != null) ...[
-            if (!showChildrenWidthsSum) const TextSpan(text: '\n'),
-            TextSpan(
-              text: '(${propertiesLocal.describeWidthConstraints()})',
-              style:
-                  propertiesLocal.constraints!.hasBoundedWidth ||
-                      !warnIfUnconstrained
-                  ? null
-                  : TextStyle(color: colorScheme.unconstrainedColor),
-            ),
-          ],
-          if (showChildrenWidthsSum)
-            TextSpan(
-              text:
-                  '\nchildren take '
-                  '${toStringAsFixed(sum(propertiesLocal.childrenWidths))}',
-            ),
-        ],
-      ),
-      propertiesLocal.isOverflowWidth,
-      colorScheme,
-    );
-    final bottom = Container(
-      margin: const EdgeInsets.only(
-        top: margin,
-        left: margin,
-        right: rightWidth,
-        bottom: minPadding,
-      ),
-      child: LayoutBuilder(
-        builder: (context, constraints) {
-          final maxWidth = constraints.maxWidth;
-          final displayWidthOutsideArrow =
-              maxWidth < minWidthToDisplayWidthInsideArrow;
-          return Column(
-            children: [
-              Truncateable(
-                truncate: !displayWidthOutsideArrow,
-                child: Container(
-                  margin: const EdgeInsets.symmetric(vertical: arrowMargin),
-                  child: ArrowWrapper.bidirectional(
-                    arrowColor: widthIndicatorColor,
-                    arrowHeadSize: arrowHeadSize,
-                    arrowStrokeWidth: arrowStrokeWidth,
-                    direction: Axis.horizontal,
-                    child: displayWidthOutsideArrow ? null : widthDescription,
-                  ),
-                ),
-              ),
-              if (displayWidthOutsideArrow)
-                Flexible(
-                  child: Container(
-                    padding: const EdgeInsets.only(top: minPadding),
-                    child: widthDescription,
-                  ),
-                ),
-            ],
-          );
-        },
-      ),
-    );
-    return BorderLayout(
-      center: child,
-      right: right,
-      rightWidth: rightWidth,
-      bottom: bottom,
-      bottomHeight: bottomHeight,
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart
deleted file mode 100644
index 4abdb55..0000000
--- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:flutter/material.dart';
-
-class WidgetTheme {
-  const WidgetTheme({this.iconAsset, this.color = otherWidgetColor});
-
-  final String? iconAsset;
-  final Color color;
-
-  static WidgetTheme fromName(String? widgetType) {
-    if (widgetType == null) {
-      return const WidgetTheme();
-    }
-
-    return themeMap[_stripBrackets(widgetType)] ?? const WidgetTheme();
-  }
-
-  /// Strips the brackets off the widget name.
-  ///
-  /// For example: `AnimatedBuilder<String>` -> `AnimatedBuilder`.
-  static String _stripBrackets(String widgetType) {
-    final bracketIndex = widgetType.indexOf('<');
-    if (bracketIndex == -1) {
-      return widgetType;
-    }
-
-    return widgetType.substring(0, bracketIndex);
-  }
-
-  static const contentWidgetColor = Color(0xff06AC3B);
-  static const highLevelWidgetColor = Color(0xffAEAEB1);
-  static const animationWidgetColor = Color(0xffE09D0E);
-  static const otherWidgetColor = Color(0xff0EA7E0);
-
-  static const animatedTheme = WidgetTheme(
-    iconAsset: WidgetIcons.animated,
-    color: animationWidgetColor,
-  );
-
-  static const transitionTheme = WidgetTheme(
-    iconAsset: WidgetIcons.transition,
-    color: animationWidgetColor,
-  );
-
-  static const textTheme = WidgetTheme(
-    iconAsset: WidgetIcons.text,
-    color: contentWidgetColor,
-  );
-
-  static const imageTheme = WidgetTheme(
-    iconAsset: WidgetIcons.image,
-    color: contentWidgetColor,
-  );
-
-  static const tabTheme = WidgetTheme(iconAsset: WidgetIcons.tab);
-  static const scrollTheme = WidgetTheme(iconAsset: WidgetIcons.scroll);
-  static const highLevelTheme = WidgetTheme(color: highLevelWidgetColor);
-  static const listTheme = WidgetTheme(iconAsset: WidgetIcons.listView);
-  static const expandTheme = WidgetTheme(iconAsset: WidgetIcons.expand);
-  static const alignTheme = WidgetTheme(iconAsset: WidgetIcons.align);
-  static const gestureTheme = WidgetTheme(iconAsset: WidgetIcons.gesture);
-  static const textButtonTheme = WidgetTheme(iconAsset: WidgetIcons.textButton);
-  static const toggleTheme = WidgetTheme(
-    iconAsset: WidgetIcons.toggle,
-    color: contentWidgetColor,
-  );
-
-  static const themeMap = <String, WidgetTheme>{
-    // High-level
-    'RenderObjectToWidgetAdapter': WidgetTheme(
-      iconAsset: WidgetIcons.root,
-      color: highLevelWidgetColor,
-    ),
-    'CupertinoApp': highLevelTheme,
-    'MaterialApp': WidgetTheme(iconAsset: WidgetIcons.materialApp),
-    'WidgetsApp': highLevelTheme,
-
-    // Text
-    'DefaultTextStyle': textTheme,
-    'RichText': textTheme,
-    'SelectableText': textTheme,
-    'Text': textTheme,
-
-    // Images
-    'Icon': imageTheme,
-    'Image': imageTheme,
-    'RawImage': imageTheme,
-
-    // Animations
-    'AnimatedAlign': animatedTheme,
-    'AnimatedBuilder': animatedTheme,
-    'AnimatedContainer': animatedTheme,
-    'AnimatedCrossFade': animatedTheme,
-    'AnimatedDefaultTextStyle': animatedTheme,
-    'AnimatedListState': animatedTheme,
-    'AnimatedModalBarrier': animatedTheme,
-    'AnimatedOpacity': animatedTheme,
-    'AnimatedPhysicalModel': animatedTheme,
-    'AnimatedPositioned': animatedTheme,
-    'AnimatedSize': animatedTheme,
-    'AnimatedWidget': animatedTheme,
-
-    // Transitions
-    'DecoratedBoxTransition': transitionTheme,
-    'FadeTransition': transitionTheme,
-    'PositionedTransition': transitionTheme,
-    'RotationTransition': transitionTheme,
-    'ScaleTransition': transitionTheme,
-    'SizeTransition': transitionTheme,
-    'SlideTransition': transitionTheme,
-    'Hero': WidgetTheme(
-      iconAsset: WidgetIcons.hero,
-      color: animationWidgetColor,
-    ),
-
-    // Scroll
-    'CustomScrollView': scrollTheme,
-    'DraggableScrollableSheet': scrollTheme,
-    'SingleChildScrollView': scrollTheme,
-    'Scrollable': scrollTheme,
-    'Scrollbar': scrollTheme,
-    'ScrollConfiguration': scrollTheme,
-    'GridView': WidgetTheme(iconAsset: WidgetIcons.gridView),
-    'ListView': listTheme,
-    'ReorderableListView': listTheme,
-    'NestedScrollView': listTheme,
-
-    // Input
-    'Checkbox': WidgetTheme(
-      iconAsset: WidgetIcons.checkbox,
-      color: contentWidgetColor,
-    ),
-    'Radio': WidgetTheme(
-      iconAsset: WidgetIcons.radio,
-      color: contentWidgetColor,
-    ),
-    'Switch': toggleTheme,
-    'CupertinoSwitch': toggleTheme,
-
-    // Layout
-    'Container': WidgetTheme(iconAsset: WidgetIcons.container),
-    'Center': WidgetTheme(iconAsset: WidgetIcons.center),
-    'Row': WidgetTheme(iconAsset: WidgetIcons.row),
-    'Column': WidgetTheme(iconAsset: WidgetIcons.column),
-    'Padding': WidgetTheme(iconAsset: WidgetIcons.padding),
-    'SizedBox': WidgetTheme(iconAsset: WidgetIcons.sizedBox),
-    'ConstrainedBox': WidgetTheme(iconAsset: WidgetIcons.constrainedBox),
-    'Align': alignTheme,
-    'Positioned': alignTheme,
-    'Expanded': expandTheme,
-    'Flexible': expandTheme,
-    'Stack': WidgetTheme(iconAsset: WidgetIcons.stack),
-    'Wrap': WidgetTheme(iconAsset: WidgetIcons.wrap),
-
-    // Buttons
-    'FloatingActionButton': WidgetTheme(
-      iconAsset: WidgetIcons.floatingActionButton,
-      color: contentWidgetColor,
-    ),
-    'InkWell': WidgetTheme(iconAsset: WidgetIcons.inkWell),
-    'GestureDetector': gestureTheme,
-    'RawGestureDetector': gestureTheme,
-    'TextButton': textButtonTheme,
-    'CupertinoButton': textButtonTheme,
-    'ElevatedButton': textButtonTheme,
-    'OutlinedButton': WidgetTheme(iconAsset: WidgetIcons.outlinedButton),
-
-    // Tabs
-    'Tab': tabTheme,
-    'TabBar': tabTheme,
-    'TabBarView': tabTheme,
-    'BottomNavigationBar': WidgetTheme(
-      iconAsset: WidgetIcons.bottomNavigationBar,
-    ),
-    'CupertinoTabScaffold': tabTheme,
-    'CupertinoTabView': tabTheme,
-
-    // Other
-    'Scaffold': WidgetTheme(iconAsset: WidgetIcons.scaffold),
-    'CircularProgressIndicator': WidgetTheme(
-      iconAsset: WidgetIcons.circularProgress,
-    ),
-    'Card': WidgetTheme(iconAsset: WidgetIcons.card),
-    'Divider': WidgetTheme(iconAsset: WidgetIcons.divider),
-    'AlertDialog': WidgetTheme(iconAsset: WidgetIcons.alertDialog),
-    'CircleAvatar': WidgetTheme(iconAsset: WidgetIcons.circleAvatar),
-    'Opacity': WidgetTheme(iconAsset: WidgetIcons.opacity),
-    'Drawer': WidgetTheme(iconAsset: WidgetIcons.drawer),
-    'PageView': WidgetTheme(iconAsset: WidgetIcons.pageView),
-    'Material': WidgetTheme(iconAsset: WidgetIcons.material),
-    'AppBar': WidgetTheme(iconAsset: WidgetIcons.appBar),
-    'HiddenGroup': WidgetTheme(iconAsset: WidgetIcons.hidden),
-  };
-}
-
-class WidgetIcons {
-  static const root = 'icons/inspector/widget_icons/root.png';
-  static const text = 'icons/inspector/widget_icons/text.png';
-  static const icon = 'icons/inspector/widget_icons/icon.png';
-  static const image = 'icons/inspector/widget_icons/image.png';
-  static const floatingActionButton =
-      'icons/inspector/widget_icons/floatingab.png';
-  static const checkbox = 'icons/inspector/widget_icons/checkbox.png';
-  static const radio = 'icons/inspector/widget_icons/radio.png';
-  static const toggle = 'icons/inspector/widget_icons/toggle.png';
-  static const animated = 'icons/inspector/widget_icons/animated.png';
-  static const transition = 'icons/inspector/widget_icons/transition.png';
-  static const hero = 'icons/inspector/widget_icons/hero.png';
-  static const container = 'icons/inspector/widget_icons/container.png';
-  static const center = 'icons/inspector/widget_icons/center.png';
-  static const row = 'icons/inspector/widget_icons/row.png';
-  static const column = 'icons/inspector/widget_icons/column.png';
-  static const padding = 'icons/inspector/widget_icons/padding.png';
-  static const scaffold = 'icons/inspector/widget_icons/scaffold.png';
-  static const sizedBox = 'icons/inspector/widget_icons/sizedbox.png';
-  static const align = 'icons/inspector/widget_icons/align.png';
-  static const scroll = 'icons/inspector/widget_icons/scroll.png';
-  static const stack = 'icons/inspector/widget_icons/stack.png';
-  static const inkWell = 'icons/inspector/widget_icons/inkwell.png';
-  static const gesture = 'icons/inspector/widget_icons/gesture.png';
-  static const textButton = 'icons/inspector/widget_icons/textbutton.png';
-  static const outlinedButton =
-      'icons/inspector/widget_icons/outlinedbutton.png';
-  static const gridView = 'icons/inspector/widget_icons/gridview.png';
-  static const listView = 'icons/inspector/widget_icons/listView.png';
-
-  static const alertDialog = 'icons/inspector/widget_icons/alertdialog.png';
-  static const card = 'icons/inspector/widget_icons/card.png';
-  static const circleAvatar = 'icons/inspector/widget_icons/circleavatar.png';
-  static const circularProgress =
-      'icons/inspector/widget_icons/circularprogress.png';
-  static const constrainedBox =
-      'icons/inspector/widget_icons/constrainedbox.png';
-  static const divider = 'icons/inspector/widget_icons/divider.png';
-  static const drawer = 'icons/inspector/widget_icons/drawer.png';
-  static const expand = 'icons/inspector/widget_icons/expand.png';
-  static const material = 'icons/inspector/widget_icons/material.png';
-  static const opacity = 'icons/inspector/widget_icons/opacity.png';
-  static const tab = 'icons/inspector/widget_icons/tab.png';
-  static const wrap = 'icons/inspector/widget_icons/wrap.png';
-  static const pageView = 'icons/inspector/widget_icons/pageView.png';
-  static const appBar = 'icons/inspector/widget_icons/appbar.png';
-  static const materialApp = 'icons/inspector/widget_icons/materialapp.png';
-  static const bottomNavigationBar =
-      'icons/inspector/widget_icons/bottomnavigationbar.png';
-  static const hidden = 'icons/inspector/widget_icons/onedot.png';
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart
deleted file mode 100644
index 710743d..0000000
--- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2024 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app_shared/shared.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/material.dart';
-
-import '../../shared/feature_flags.dart';
-import '../../shared/framework/screen.dart';
-import '../../shared/globals.dart';
-import '../inspector/inspector_screen_body.dart' as legacy;
-import '../inspector_v2/inspector_screen_body.dart' as v2;
-import 'inspector_screen_controller.dart';
-
-class InspectorScreen extends Screen {
-  InspectorScreen() : super.fromMetaData(ScreenMetaData.inspector);
-
-  static const minScreenWidthForText = 900.0;
-
-  static final id = ScreenMetaData.inspector.id;
-
-  // There is not enough room to safely show the console in the embed view of
-  // the DevTools and IDEs have their own consoles.
-  @override
-  bool showConsole(EmbedMode embedMode) => !embedMode.embedded;
-
-  @override
-  bool showAiAssistant() => true;
-
-  @override
-  String get docPageId => screenId;
-
-  @override
-  Widget buildScreenBody(BuildContext context) =>
-      const InspectorScreenSwitcher();
-}
-
-class InspectorScreenSwitcher extends StatefulWidget {
-  const InspectorScreenSwitcher({super.key});
-
-  @override
-  State<InspectorScreenSwitcher> createState() =>
-      _InspectorScreenSwitcherState();
-}
-
-class _InspectorScreenSwitcherState extends State<InspectorScreenSwitcher>
-    with AutoDisposeMixin {
-  late InspectorScreenController controller;
-
-  bool get shouldShowInspectorV2 =>
-      FeatureFlags.inspectorV2.isEnabled &&
-      !preferences.inspector.legacyInspectorEnabled.value;
-
-  @override
-  void initState() {
-    super.initState();
-    controller = screenControllers.lookup<InspectorScreenController>();
-    addAutoDisposeListener(
-      preferences.inspector.legacyInspectorEnabled,
-      () async {
-        controller.legacyInspectorController.setVisibleToUser(
-          !shouldShowInspectorV2,
-        );
-        await controller.v2InspectorController.setVisibleToUser(
-          shouldShowInspectorV2,
-        );
-      },
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return ValueListenableBuilder(
-      valueListenable: preferences.inspector.legacyInspectorEnabled,
-      builder: (context, _, _) {
-        if (shouldShowInspectorV2) {
-          return v2.InspectorScreenBody(
-            controller: controller.v2InspectorController,
-          );
-        }
-
-        return legacy.InspectorScreenBody(
-          controller: controller.legacyInspectorController,
-        );
-      },
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen_controller.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen_controller.dart
deleted file mode 100644
index 5ca8073..0000000
--- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen_controller.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2024 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import '../../shared/analytics/metrics.dart';
-import '../../shared/console/primitives/simple_items.dart';
-import '../../shared/framework/screen.dart';
-import '../../shared/framework/screen_controllers.dart';
-import '../inspector/inspector_controller.dart' as legacy;
-import '../inspector/inspector_tree_controller.dart' as legacy;
-import '../inspector_v2/inspector_controller.dart' as v2;
-import '../inspector_v2/inspector_tree_controller.dart' as v2;
-
-/// Screen controller for the Inspector screen.
-///
-/// This controller can be accessed from anywhere in DevTools, as long as it was
-/// first registered, by
-/// calling `screenControllers.lookup<InspectorScreenController>()`.
-///
-/// The controller lifecycle is managed by the [ScreenControllers] class. The
-/// `init` method is called lazily upon the first controller access from
-/// `screenControllers`. The `dispose` method is called by `screenControllers`
-/// when DevTools is destroying a set of DevTools screen controllers.
-class InspectorScreenController extends DevToolsScreenController {
-  @override
-  final screenId = ScreenMetaData.inspector.id;
-
-  late v2.InspectorController v2InspectorController;
-  late v2.InspectorTreeController v2InspectorTreeController;
-
-  late legacy.InspectorController legacyInspectorController;
-  late legacy.InspectorTreeController legacyInspectorTreeController;
-  late legacy.InspectorTreeController legacyDetailsTreeController;
-
-  @override
-  void init() {
-    super.init();
-    v2InspectorTreeController = v2.InspectorTreeController(
-      gaId: InspectorScreenMetrics.summaryTreeGaId,
-    );
-    v2InspectorController = v2.InspectorController(
-      inspectorTree: v2InspectorTreeController,
-      treeType: FlutterTreeType.widget,
-    );
-
-    // TODO(elliette): Remove legacy inspector.
-    legacyInspectorTreeController = legacy.InspectorTreeController(
-      gaId: InspectorScreenMetrics.summaryTreeGaId,
-    );
-    legacyDetailsTreeController = legacy.InspectorTreeController(
-      gaId: InspectorScreenMetrics.detailsTreeGaId,
-    );
-    legacyInspectorController = legacy.InspectorController(
-      inspectorTree: legacyInspectorTreeController,
-      detailsTree: legacyDetailsTreeController,
-      treeType: FlutterTreeType.widget,
-    );
-  }
-
-  @override
-  void dispose() {
-    v2InspectorTreeController.dispose();
-    v2InspectorController.dispose();
-
-    legacyInspectorTreeController.dispose();
-    legacyDetailsTreeController.dispose();
-    legacyInspectorController.dispose();
-    super.dispose();
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart
deleted file mode 100644
index 823a3dd..0000000
--- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_settings_dialog.dart
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2024 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:async';
-
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/material.dart';
-import 'package:vm_service/vm_service.dart' hide Stack;
-
-import '../../shared/analytics/analytics.dart' as ga;
-import '../../shared/analytics/constants.dart' as gac;
-import '../../shared/feature_flags.dart';
-import '../../shared/globals.dart';
-import '../../shared/managers/banner_messages.dart';
-import '../../shared/preferences/preferences.dart';
-import '../../shared/primitives/simple_items.dart';
-import '../../shared/ui/common_widgets.dart';
-import '../../shared/ui/editable_list.dart';
-import 'inspector_screen.dart';
-
-class FlutterInspectorSettingsDialog extends StatefulWidget {
-  const FlutterInspectorSettingsDialog({super.key});
-
-  @override
-  State<FlutterInspectorSettingsDialog> createState() =>
-      _FlutterInspectorSettingsDialogState();
-}
-
-class _FlutterInspectorSettingsDialogState
-    extends State<FlutterInspectorSettingsDialog>
-    with AutoDisposeMixin {
-  @override
-  void initState() {
-    super.initState();
-    addAutoDisposeListener(preferences.inspector.legacyInspectorEnabled, () {
-      if (!preferences.inspector.legacyInspectorEnabled.value) {
-        bannerMessages.removeMessageByKey(
-          LegacyInspectorWarningMessage.buildKey(InspectorScreen.id),
-          InspectorScreen.id,
-        );
-      }
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final theme = Theme.of(context);
-    const dialogHeight = 500.0;
-
-    return ValueListenableBuilder(
-      valueListenable: preferences.inspector.legacyInspectorEnabled,
-      builder: (context, legacyInspectorEnabled, _) {
-        final inspectorV2Enabled = !legacyInspectorEnabled;
-        return DevToolsDialog(
-          title: const DialogTitleText('Flutter Inspector Settings'),
-          content: SizedBox(
-            width: defaultDialogWidth,
-            height: dialogHeight,
-            child: Column(
-              mainAxisSize: MainAxisSize.min,
-              crossAxisAlignment: CrossAxisAlignment.start,
-              children: [
-                ...dialogSubHeader(theme, 'General'),
-                CheckboxSetting(
-                  notifier:
-                      preferences.inspector.hoverEvalModeEnabled
-                          as ValueNotifier<bool?>,
-                  title: 'Enable hover inspection',
-                  description:
-                      'Hovering over any widget displays its properties and values.',
-                  gaItem: gac.inspectorHoverEvalMode,
-                ),
-                const SizedBox(height: largeSpacing),
-                if (inspectorV2Enabled) ...[
-                  CheckboxSetting(
-                    notifier:
-                        preferences.inspector.autoRefreshEnabled
-                            as ValueNotifier<bool?>,
-                    title: 'Enable widget tree auto-refreshing',
-                    description:
-                        'The widget tree will automatically refresh after a hot-reload or navigation event.',
-                    gaItem: gac.inspectorAutoRefreshEnabled,
-                  ),
-                ] else ...[
-                  const InspectorDefaultDetailsViewOption(),
-                ],
-                const SizedBox(height: largeSpacing),
-                // TODO(https://github.com/flutter/devtools/issues/7860): Clean-up
-                // after Inspector V2 has been released.
-                if (FeatureFlags.inspectorV2.isEnabled)
-                  Flexible(
-                    child: CheckboxSetting(
-                      notifier:
-                          preferences.inspector.legacyInspectorEnabled
-                              as ValueNotifier<bool?>,
-                      title: 'Use legacy inspector',
-                      description:
-                          'Disable the redesigned Flutter inspector. Please know that '
-                          'the legacy inspector will be removed in a future release.',
-                      gaItem: gac.inspectorV2Disabled,
-                    ),
-                  ),
-                const SizedBox(height: largeSpacing),
-                ...dialogSubHeader(theme, 'Package Directories'),
-                Row(
-                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                  children: [
-                    Expanded(
-                      child: Text(
-                        'Widgets in these directories will show up in your summary tree.',
-                        style: theme.subtleTextStyle,
-                      ),
-                    ),
-                    MoreInfoLink(
-                      url: DocLinks.inspectorPackageDirectories.value,
-                      gaScreenName: gac.inspector,
-                      gaSelectedItemDescription:
-                          gac.InspectorDocs.packageDirectoriesDocs.name,
-                    ),
-                  ],
-                ),
-                Text(
-                  '(e.g. /absolute/path/to/myPackage/)',
-                  style: theme.subtleTextStyle,
-                ),
-                const SizedBox(height: denseSpacing),
-                const Expanded(child: PubRootDirectorySection()),
-              ],
-            ),
-          ),
-          actions: const [DialogCloseButton()],
-        );
-      },
-    );
-  }
-}
-
-class InspectorDefaultDetailsViewOption extends StatelessWidget {
-  const InspectorDefaultDetailsViewOption({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return ValueListenableBuilder(
-      valueListenable: preferences.inspector.defaultDetailsView,
-      builder: (context, selection, _) {
-        final theme = Theme.of(context);
-        return Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            Text(
-              'Select the default tab for the inspector.',
-              style: theme.subtleTextStyle,
-            ),
-            const SizedBox(height: denseSpacing),
-            RadioGroup(
-              groupValue: selection,
-              onChanged: _onChanged,
-              child: Row(
-                mainAxisSize: MainAxisSize.min,
-                children: [
-                  const Radio<InspectorDetailsViewType>(
-                    value: InspectorDetailsViewType.layoutExplorer,
-                    materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
-                  ),
-                  Text(InspectorDetailsViewType.layoutExplorer.key),
-                  const SizedBox(width: denseSpacing),
-                  const Radio<InspectorDetailsViewType>(
-                    materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
-                    value: InspectorDetailsViewType.widgetDetailsTree,
-                  ),
-                  Text(InspectorDetailsViewType.widgetDetailsTree.key),
-                ],
-              ),
-            ),
-          ],
-        );
-      },
-    );
-  }
-
-  void _onChanged(InspectorDetailsViewType? value) {
-    if (value != null) {
-      preferences.inspector.setDefaultInspectorDetailsView(value);
-      final item = value.name == InspectorDetailsViewType.layoutExplorer.name
-          ? gac.defaultDetailsViewToLayoutExplorer
-          : gac.defaultDetailsViewToWidgetDetails;
-      ga.select(gac.inspector, item);
-    }
-  }
-}
-
-class PubRootDirectorySection extends StatelessWidget {
-  const PubRootDirectorySection({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return ValueListenableBuilder<IsolateRef?>(
-      valueListenable:
-          serviceConnection.serviceManager.isolateManager.mainIsolate,
-      builder: (_, _, _) {
-        return SizedBox(
-          height: 200.0,
-          child: EditableList(
-            gaScreen: gac.inspector,
-            gaRefreshSelection: gac.refreshPubRoots,
-            entries: preferences.inspector.pubRootDirectories,
-            textFieldLabel: 'Enter a new package directory',
-            isRefreshing: preferences.inspector.isRefreshingPubRootDirectories,
-            onEntryAdded: (p0) => unawaited(
-              preferences.inspector.addPubRootDirectories([
-                p0,
-              ], shouldCache: true),
-            ),
-            onEntryRemoved: (p0) =>
-                unawaited(preferences.inspector.removePubRootDirectories([p0])),
-            onRefreshTriggered: () =>
-                unawaited(preferences.inspector.loadPubRootDirectories()),
-          ),
-        );
-      },
-    );
-  }
-}
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart
index 32de022..f8694bc 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart
@@ -36,8 +36,8 @@
 import '../../shared/primitives/query_parameters.dart';
 import '../../shared/primitives/utils.dart';
 import '../../shared/utils/utils.dart';
-import '../inspector_shared/inspector_screen.dart';
 import 'inspector_data_models.dart';
+import 'inspector_screen.dart';
 import 'inspector_tree_controller.dart';
 
 final _log = Logger('inspector_controller');
diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controls.dart
similarity index 95%
rename from packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart
rename to packages/devtools_app/lib/src/screens/inspector_v2/inspector_controls.dart
index d1f810a..2f1e53b 100644
--- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_controls.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controls.dart
@@ -13,14 +13,14 @@
 import '../../shared/feature_flags.dart';
 import '../../shared/globals.dart';
 import '../../shared/ui/common_widgets.dart';
-import '../inspector_shared/inspector_settings_dialog.dart';
-import '../inspector_v2/inspector_controller.dart' as v2;
+import 'inspector_controller.dart';
+import 'inspector_settings_dialog.dart';
 
 /// Control buttons for the inspector panel.
 class InspectorControls extends StatelessWidget {
   const InspectorControls({super.key, this.controller});
 
-  final v2.InspectorController? controller;
+  final InspectorController? controller;
 
   static const minScreenWidthForTextBeforeTruncating = 800.0;
   static const minScreenWidthForText = 550.0;
@@ -113,7 +113,7 @@
 class ShowImplementationWidgetsButton extends StatelessWidget {
   const ShowImplementationWidgetsButton({super.key, required this.controller});
 
-  final v2.InspectorController controller;
+  final InspectorController controller;
 
   @override
   Widget build(BuildContext context) {
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart
index 188dabd..1d166ce 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_data_models.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
-/// @docImport '../inspector/layout_explorer/ui/overflow_indicator_painter.dart';
+/// @docImport '../inspector_v2/layout_explorer/ui/overflow_indicator_painter.dart';
 library;
 
 import 'dart:math' as math;
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen.dart
new file mode 100644
index 0000000..1ac60f6
--- /dev/null
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen.dart
@@ -0,0 +1,36 @@
+// Copyright 2024 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import 'package:devtools_app_shared/shared.dart';
+import 'package:flutter/material.dart';
+
+import '../../shared/framework/screen.dart';
+import '../../shared/globals.dart';
+import 'inspector_screen_body.dart';
+import 'inspector_screen_controller.dart';
+
+class InspectorScreen extends Screen {
+  InspectorScreen() : super.fromMetaData(ScreenMetaData.inspector);
+
+  static const minScreenWidthForText = 900.0;
+
+  static final id = ScreenMetaData.inspector.id;
+
+  // There is not enough room to safely show the console in the embed view of
+  // the DevTools and IDEs have their own consoles.
+  @override
+  bool showConsole(EmbedMode embedMode) => !embedMode.embedded;
+
+  @override
+  bool showAiAssistant() => true;
+
+  @override
+  String get docPageId => screenId;
+
+  @override
+  Widget buildScreenBody(BuildContext context) {
+    final controller = screenControllers.lookup<InspectorScreenController>();
+    return InspectorScreenBody(controller: controller.inspectorController);
+  }
+}
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart
index bcb6070..b43e9ff 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart
@@ -19,9 +19,9 @@
 import '../../shared/ui/common_widgets.dart';
 import '../../shared/ui/search.dart';
 import '../../shared/utils/utils.dart';
-import '../inspector_shared/inspector_controls.dart';
-import '../inspector_shared/inspector_screen.dart';
 import 'inspector_controller.dart';
+import 'inspector_controls.dart';
+import 'inspector_screen.dart';
 import 'inspector_tree_controller.dart';
 import 'widget_details.dart';
 
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_controller.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_controller.dart
new file mode 100644
index 0000000..5a403db
--- /dev/null
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_controller.dart
@@ -0,0 +1,47 @@
+// Copyright 2024 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import '../../shared/analytics/metrics.dart';
+import '../../shared/console/primitives/simple_items.dart';
+import '../../shared/framework/screen.dart';
+import '../../shared/framework/screen_controllers.dart';
+import 'inspector_controller.dart';
+import 'inspector_tree_controller.dart';
+
+/// Screen controller for the Inspector screen.
+///
+/// This controller can be accessed from anywhere in DevTools, as long as it was
+/// first registered, by
+/// calling `screenControllers.lookup<InspectorScreenController>()`.
+///
+/// The controller lifecycle is managed by the [ScreenControllers] class. The
+/// `init` method is called lazily upon the first controller access from
+/// `screenControllers`. The `dispose` method is called by `screenControllers`
+/// when DevTools is destroying a set of DevTools screen controllers.
+class InspectorScreenController extends DevToolsScreenController {
+  @override
+  final screenId = ScreenMetaData.inspector.id;
+
+  late InspectorController inspectorController;
+  late InspectorTreeController inspectorTreeController;
+
+  @override
+  void init() {
+    super.init();
+    inspectorTreeController = InspectorTreeController(
+      gaId: InspectorScreenMetrics.summaryTreeGaId,
+    );
+    inspectorController = InspectorController(
+      inspectorTree: inspectorTreeController,
+      treeType: FlutterTreeType.widget,
+    );
+  }
+
+  @override
+  void dispose() {
+    inspectorTreeController.dispose();
+    inspectorController.dispose();
+    super.dispose();
+  }
+}
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_settings_dialog.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_settings_dialog.dart
new file mode 100644
index 0000000..a185822
--- /dev/null
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_settings_dialog.dart
@@ -0,0 +1,127 @@
+// Copyright 2024 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import 'dart:async';
+
+import 'package:devtools_app_shared/ui.dart';
+import 'package:devtools_app_shared/utils.dart';
+import 'package:flutter/material.dart';
+import 'package:vm_service/vm_service.dart' hide Stack;
+
+import '../../shared/analytics/constants.dart' as gac;
+import '../../shared/globals.dart';
+import '../../shared/primitives/simple_items.dart';
+import '../../shared/ui/common_widgets.dart';
+import '../../shared/ui/editable_list.dart';
+
+class FlutterInspectorSettingsDialog extends StatefulWidget {
+  const FlutterInspectorSettingsDialog({super.key});
+
+  @override
+  State<FlutterInspectorSettingsDialog> createState() =>
+      _FlutterInspectorSettingsDialogState();
+}
+
+class _FlutterInspectorSettingsDialogState
+    extends State<FlutterInspectorSettingsDialog>
+    with AutoDisposeMixin {
+  @override
+  Widget build(BuildContext context) {
+    final theme = Theme.of(context);
+    const dialogHeight = 500.0;
+
+    return DevToolsDialog(
+      title: const DialogTitleText('Flutter Inspector Settings'),
+      content: SizedBox(
+        width: defaultDialogWidth,
+        height: dialogHeight,
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            ...dialogSubHeader(theme, 'General'),
+            CheckboxSetting(
+              notifier:
+                  preferences.inspector.hoverEvalModeEnabled
+                      as ValueNotifier<bool?>,
+              title: 'Enable hover inspection',
+              description:
+                  'Hovering over any widget displays its properties and values.',
+              gaItem: gac.inspectorHoverEvalMode,
+            ),
+            const SizedBox(height: largeSpacing),
+            CheckboxSetting(
+              notifier:
+                  preferences.inspector.autoRefreshEnabled
+                      as ValueNotifier<bool?>,
+              title: 'Enable widget tree auto-refreshing',
+              description:
+                  'The widget tree will automatically refresh after a hot-reload or navigation event.',
+              gaItem: gac.inspectorAutoRefreshEnabled,
+            ),
+            const SizedBox(height: largeSpacing),
+            ...dialogSubHeader(theme, 'Package Directories'),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Expanded(
+                  child: Text(
+                    'Widgets in these directories will show up in your summary tree.',
+                    style: theme.subtleTextStyle,
+                  ),
+                ),
+                MoreInfoLink(
+                  url: DocLinks.inspectorPackageDirectories.value,
+                  gaScreenName: gac.inspector,
+                  gaSelectedItemDescription:
+                      gac.InspectorDocs.packageDirectoriesDocs.name,
+                ),
+              ],
+            ),
+            Text(
+              '(e.g. /absolute/path/to/myPackage/)',
+              style: theme.subtleTextStyle,
+            ),
+            const SizedBox(height: denseSpacing),
+            const Expanded(child: PubRootDirectorySection()),
+          ],
+        ),
+      ),
+      actions: const [DialogCloseButton()],
+    );
+  }
+}
+
+class PubRootDirectorySection extends StatelessWidget {
+  const PubRootDirectorySection({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return ValueListenableBuilder<IsolateRef?>(
+      valueListenable:
+          serviceConnection.serviceManager.isolateManager.mainIsolate,
+      builder: (_, _, _) {
+        return SizedBox(
+          height: 200.0,
+          child: EditableList(
+            gaScreen: gac.inspector,
+            gaRefreshSelection: gac.refreshPubRoots,
+            entries: preferences.inspector.pubRootDirectories,
+            textFieldLabel: 'Enter a new package directory',
+            isRefreshing: preferences.inspector.isRefreshingPubRootDirectories,
+            onEntryAdded: (p0) => unawaited(
+              preferences.inspector.addPubRootDirectories([
+                p0,
+              ], shouldCache: true),
+            ),
+            onEntryRemoved: (p0) =>
+                unawaited(preferences.inspector.removePubRootDirectories([p0])),
+            onRefreshTriggered: () =>
+                unawaited(preferences.inspector.loadPubRootDirectories()),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart
index 5b4b1ec..859b650 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/layout_explorer/ui/utils.dart
@@ -9,8 +9,8 @@
 
 import '../../../../shared/diagnostics/diagnostics_node.dart';
 import '../../../../shared/primitives/utils.dart';
-import '../../../inspector/layout_explorer/ui/dimension.dart';
 import '../../inspector_data_models.dart';
+import 'dimension.dart';
 import 'overflow_indicator_painter.dart';
 import 'theme.dart';
 import 'widgets_theme.dart';
diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart
index da6f1ce..786ff86 100644
--- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart
+++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart
@@ -27,7 +27,7 @@
 import '../../shared/primitives/utils.dart';
 import '../../shared/ui/filter.dart';
 import '../../shared/ui/search.dart';
-import '../inspector/inspector_tree_controller.dart';
+import '../inspector_v2/inspector_tree_controller.dart';
 import 'log_details_controller.dart';
 import 'logging_screen.dart';
 import 'metadata.dart';
diff --git a/packages/devtools_app/lib/src/shared/analytics/constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants.dart
index 45450f8..aaf721b 100644
--- a/packages/devtools_app/lib/src/shared/analytics/constants.dart
+++ b/packages/devtools_app/lib/src/shared/analytics/constants.dart
@@ -8,7 +8,6 @@
 import 'package:devtools_shared/devtools_extensions.dart';
 
 import '../framework/screen.dart';
-import '../preferences/preferences.dart';
 
 part 'constants/_cpu_profiler_constants.dart';
 part 'constants/_debugger_constants.dart';
@@ -97,6 +96,9 @@
 const inspectorSettings = 'inspectorSettings';
 const loggingSettings = 'loggingSettings';
 const refreshPubRoots = 'refreshPubRoots';
+
+enum InspectorDetailsViewType { layoutExplorer, widgetDetailsTree }
+
 final defaultDetailsViewToLayoutExplorer =
     InspectorDetailsViewType.layoutExplorer.name;
 final defaultDetailsViewToWidgetDetails =
diff --git a/packages/devtools_app/lib/src/shared/analytics/metrics.dart b/packages/devtools_app/lib/src/shared/analytics/metrics.dart
index fa0195a..a1be45f 100644
--- a/packages/devtools_app/lib/src/shared/analytics/metrics.dart
+++ b/packages/devtools_app/lib/src/shared/analytics/metrics.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
-/// @docImport '../../screens/inspector/inspector_tree_controller.dart';
+/// @docImport '../../screens/inspector_v2/inspector_tree_controller.dart';
 /// @docImport '../../screens/performance/panes/flutter_frames/flutter_frame_model.dart';
 library;
 
@@ -67,12 +67,6 @@
 }
 
 class InspectorScreenMetrics extends ScreenAnalyticsMetrics {
-  InspectorScreenMetrics.legacy({
-    this.rootSetCount,
-    this.rowCount,
-    this.inspectorTreeControllerId,
-  }) : isV2 = false;
-
   InspectorScreenMetrics.v2({
     this.rootSetCount,
     this.rowCount,
diff --git a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart
deleted file mode 100644
index 1afbf48..0000000
--- a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-/// Inspector specific tree rendering support.
-///
-/// This library must not have direct dependencies on web-only libraries.
-///
-/// This allows tests of the complicated logic in this class to run on the VM.
-library;
-
-import 'package:flutter/foundation.dart';
-
-import '../../diagnostics/diagnostics_node.dart';
-import '../../ui/search.dart';
-
-/// Split text into two groups, word characters at the start of a string and all
-/// other characters.
-final treeNodePrimaryDescriptionPattern = RegExp(r'^([\w ]+)(.*)$');
-// TODO(jacobr): temporary workaround for missing structure from assertion thrown building
-// widget errors.
-final assertionThrownBuildingError = RegExp(
-  r'^(The following assertion was thrown building [a-zA-Z]+)(\(.*\))(:)$',
-);
-
-typedef TreeEventCallback = void Function(InspectorTreeNode node);
-
-const iconPadding = 4.0;
-const chartLineStrokeWidth = 1.0;
-const inspectorColumnWidth = 12.0;
-const inspectorRowHeight = 16.0;
-
-/// This class could be refactored out to be a reasonable generic collapsible
-/// tree ui node class but we choose to instead make it widget inspector
-/// specific as that is the only case we care about.
-// TODO(kenz): extend TreeNode class to share tree logic.
-class InspectorTreeNode {
-  InspectorTreeNode({InspectorTreeNode? parent, bool expandChildren = true})
-    : _children = <InspectorTreeNode>[],
-      _parent = parent,
-      _isExpanded = expandChildren;
-
-  bool get showLinesToChildren {
-    return _children.length > 1 && !_children.last.isProperty;
-  }
-
-  bool get isDirty => _isDirty;
-  bool _isDirty = true;
-
-  set isDirty(bool dirty) {
-    if (dirty) {
-      _isDirty = true;
-      _shouldShow = null;
-      if (_childrenCount == null) {
-        // Already dirty.
-        return;
-      }
-      _childrenCount = null;
-      if (parent != null) {
-        parent!.isDirty = true;
-      }
-    } else {
-      _isDirty = false;
-    }
-  }
-
-  /// Returns whether the node is currently visible in the tree.
-  void updateShouldShow(bool value) {
-    if (value != _shouldShow) {
-      _shouldShow = value;
-      for (final child in children) {
-        child.updateShouldShow(value);
-      }
-    }
-  }
-
-  bool get shouldShow {
-    final parentLocal = parent;
-    _shouldShow ??=
-        parentLocal == null || parentLocal.isExpanded && parentLocal.shouldShow;
-    return _shouldShow!;
-  }
-
-  bool? _shouldShow;
-
-  bool selected = false;
-
-  RemoteDiagnosticsNode? _diagnostic;
-  final List<InspectorTreeNode> _children;
-
-  Iterable<InspectorTreeNode> get children => _children;
-
-  bool get isProperty {
-    final diagnosticLocal = diagnostic;
-    return diagnosticLocal == null || diagnosticLocal.isProperty;
-  }
-
-  bool get isExpanded => _isExpanded;
-  bool _isExpanded;
-
-  bool allowExpandCollapse = true;
-
-  bool get showExpandCollapse {
-    return (diagnostic?.hasChildren == true || children.isNotEmpty) &&
-        allowExpandCollapse;
-  }
-
-  set isExpanded(bool value) {
-    if (value != _isExpanded) {
-      _isExpanded = value;
-      isDirty = true;
-      if (_shouldShow ?? false) {
-        for (final child in children) {
-          child.updateShouldShow(value);
-        }
-      }
-    }
-  }
-
-  InspectorTreeNode? get parent => _parent;
-  InspectorTreeNode? _parent;
-
-  set parent(InspectorTreeNode? value) {
-    _parent = value;
-    _parent?.isDirty = true;
-  }
-
-  RemoteDiagnosticsNode? get diagnostic => _diagnostic;
-
-  set diagnostic(RemoteDiagnosticsNode? v) {
-    final value = v!;
-    _diagnostic = value;
-    _isExpanded = value.childrenReady;
-    isDirty = true;
-  }
-
-  int get childrenCount {
-    if (!isExpanded) {
-      _childrenCount = 0;
-    }
-    final childrenCountLocal = _childrenCount;
-    if (childrenCountLocal != null) {
-      return childrenCountLocal;
-    }
-    int count = 0;
-    for (final child in _children) {
-      count += child.subtreeSize;
-    }
-    return _childrenCount = count;
-  }
-
-  bool get hasPlaceholderChildren {
-    return children.length == 1 && children.first.diagnostic == null;
-  }
-
-  int? _childrenCount;
-
-  int get subtreeSize => childrenCount + 1;
-
-  // TODO(jacobr): move getRowIndex to the InspectorTree class.
-  int getRowIndex(InspectorTreeNode node) {
-    int index = 0;
-    while (true) {
-      final parent = node.parent;
-      if (parent == null) {
-        break;
-      }
-      for (final sibling in parent._children) {
-        if (sibling == node) {
-          break;
-        }
-        index += sibling.subtreeSize;
-      }
-      index += 1; // For parent itself.
-      node = parent;
-    }
-    return index;
-  }
-
-  // TODO(jacobr): move this method to the InspectorTree class.
-  // TODO: optimize this method.
-  InspectorTreeRow? getRow(int index) {
-    if (subtreeSize <= index) {
-      return null;
-    }
-
-    final ticks = <int>[];
-    InspectorTreeNode node = this;
-    int current = 0;
-    int depth = 0;
-
-    // Iterate till getting the result to return.
-    while (true) {
-      final style = node.diagnostic?.style;
-      final indented =
-          style != DiagnosticsTreeStyle.flat &&
-          style != DiagnosticsTreeStyle.error;
-      if (current == index) {
-        return InspectorTreeRow(
-          node: node,
-          index: index,
-          ticks: ticks,
-          depth: depth,
-          lineToParent:
-              !node.isProperty &&
-              index != 0 &&
-              node.parent!.showLinesToChildren,
-        );
-      }
-      assert(index > current);
-      current++;
-      final children = node._children;
-      int i;
-      for (i = 0; i < children.length; ++i) {
-        final child = children[i];
-        final subtreeSize = child.subtreeSize;
-        if (current + subtreeSize > index) {
-          node = child;
-          if (children.length > 1 &&
-              i + 1 != children.length &&
-              !children.last.isProperty) {
-            if (indented) {
-              ticks.add(depth);
-            }
-          }
-          break;
-        }
-        current += subtreeSize;
-      }
-      assert(i < children.length);
-      if (indented) {
-        depth++;
-      }
-    }
-  }
-
-  void removeChild(InspectorTreeNode child) {
-    child.parent = null;
-    final removed = _children.remove(child);
-    assert(removed);
-    isDirty = true;
-  }
-
-  void appendChild(InspectorTreeNode child) {
-    _children.add(child);
-    child.parent = this;
-    isDirty = true;
-  }
-
-  void clearChildren() {
-    _children.clear();
-    isDirty = true;
-  }
-}
-
-/// A row in the tree with all information required to render it.
-class InspectorTreeRow with SearchableDataMixin {
-  InspectorTreeRow({
-    required this.node,
-    required this.index,
-    required this.ticks,
-    required this.depth,
-    required this.lineToParent,
-  });
-
-  final InspectorTreeNode node;
-
-  /// Column indexes of ticks to draw lines from parents to children.
-  final List<int> ticks;
-  final int depth;
-  final int index;
-  final bool lineToParent;
-
-  bool get isSelected => node.selected;
-}
-
-/// Callback issued every time a node is added to the tree.
-typedef NodeAddedCallback =
-    void Function(
-      InspectorTreeNode node,
-      RemoteDiagnosticsNode diagnosticsNode,
-    );
-
-class InspectorTreeConfig {
-  InspectorTreeConfig({
-    this.onNodeAdded,
-    this.onClientActiveChange,
-    this.onSelectionChange,
-    this.onExpand,
-  });
-
-  final NodeAddedCallback? onNodeAdded;
-  final VoidCallback? onSelectionChange;
-  final void Function(bool added)? onClientActiveChange;
-  final TreeEventCallback? onExpand;
-}
-
-enum SearchTargetType {
-  widget,
-  // TODO(https://github.com/flutter/devtools/issues/3489) implement other search scopes: details, all etc
-}
diff --git a/packages/devtools_app/lib/src/shared/console/widgets/description.dart b/packages/devtools_app/lib/src/shared/console/widgets/description.dart
index 7ea8389..f7006f9 100644
--- a/packages/devtools_app/lib/src/shared/console/widgets/description.dart
+++ b/packages/devtools_app/lib/src/shared/console/widgets/description.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
-/// @docImport '../../../screens/inspector/inspector_tree_controller.dart';
+/// @docImport '../../../screens/inspector_v2/inspector_tree_controller.dart';
 library;
 
 import 'package:devtools_app_shared/ui.dart';
@@ -17,7 +17,7 @@
 import '../../ui/hover.dart';
 import '../../ui/icons.dart';
 import '../../ui/utils.dart';
-import '../eval/inspector_tree.dart';
+import '../eval/inspector_tree_v2.dart';
 import 'expandable_variable.dart';
 
 final _colorIconMaker = ColorIconMaker();
diff --git a/packages/devtools_app/lib/src/shared/managers/error_badge_manager.dart b/packages/devtools_app/lib/src/shared/managers/error_badge_manager.dart
index d3d3f7d..aadfe08 100644
--- a/packages/devtools_app/lib/src/shared/managers/error_badge_manager.dart
+++ b/packages/devtools_app/lib/src/shared/managers/error_badge_manager.dart
@@ -11,7 +11,7 @@
 import 'package:flutter/foundation.dart';
 import 'package:vm_service/vm_service.dart';
 
-import '../../screens/inspector_shared/inspector_screen.dart';
+import '../../screens/inspector_v2/inspector_screen.dart';
 import '../../screens/logging/logging_screen.dart';
 import '../../screens/network/network_screen.dart';
 import '../../screens/performance/performance_screen.dart';
diff --git a/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart b/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart
index 440c2cc..7efdbcb 100644
--- a/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart
+++ b/packages/devtools_app/lib/src/shared/preferences/_inspector_preferences.dart
@@ -4,25 +4,10 @@
 
 part of 'preferences.dart';
 
-enum InspectorDetailsViewType {
-  layoutExplorer(nameOverride: 'Layout Explorer'),
-  widgetDetailsTree(nameOverride: 'Widget Details Tree');
-
-  const InspectorDetailsViewType({String? nameOverride})
-    : _nameOverride = nameOverride;
-
-  final String? _nameOverride;
-
-  String get key => _nameOverride ?? name;
-}
-
 class InspectorPreferencesController extends DisposableController
     with AutoDisposeControllerMixin {
   ValueListenable<bool> get hoverEvalModeEnabled => _hoverEvalMode;
-  ValueListenable<bool> get legacyInspectorEnabled => _legacyInspectorEnabled;
   ValueListenable<bool> get autoRefreshEnabled => _autoRefreshEnabled;
-  ValueListenable<InspectorDetailsViewType> get defaultDetailsView =>
-      _defaultDetailsView;
   ListValueNotifier<String> get pubRootDirectories => _pubRootDirectories;
   ValueListenable<bool> get isRefreshingPubRootDirectories =>
       _pubRootDirectoriesAreBusy;
@@ -30,21 +15,13 @@
       serviceConnection.inspectorService;
 
   final _hoverEvalMode = ValueNotifier<bool>(false);
-  final _legacyInspectorEnabled = ValueNotifier<bool>(false);
   final _autoRefreshEnabled = ValueNotifier<bool>(true);
   final _pubRootDirectories = ListValueNotifier<String>([]);
   final _pubRootDirectoriesAreBusy = ValueNotifier<bool>(false);
   final _busyCounter = ValueNotifier<int>(0);
-  final _defaultDetailsView = ValueNotifier<InspectorDetailsViewType>(
-    InspectorDetailsViewType.layoutExplorer,
-  );
 
   static const _hoverEvalModeStorageId = 'inspector.hoverEvalMode';
-  static const _legacyInspectorEnabledStorageId =
-      'inspector.legacyInspectorEnabled';
   static const _autoRefreshEnabledStorageId = 'inspector.autoRefreshEnabled';
-  static const _defaultDetailsViewStorageId =
-      'inspector.defaultDetailsViewType';
   static const _customPubRootDirectoriesStoragePrefix =
       'inspector.customPubRootDirectories';
 
@@ -83,11 +60,8 @@
   @override
   Future<void> init() async {
     await _initHoverEvalMode();
-    await _initLegacyInspectorEnabled();
     await _initAutoRefreshEnabled();
-    // TODO(jacobr): consider initializing this first as it is not blocking.
     _initPubRootDirectories();
-    await _initDefaultInspectorDetailsView();
   }
 
   Future<void> _initHoverEvalMode() async {
@@ -98,16 +72,6 @@
     );
   }
 
-  Future<void> _initLegacyInspectorEnabled() async {
-    // TODO(https://github.com/flutter/devtools/issues/8667): Consider removing
-    // the old 'inspector.inspectorV2Enabled' key if it is set.
-    await _updateLegacyInspectorEnabled();
-    _saveBooleanPreferenceChanges(
-      preferenceStorageId: _legacyInspectorEnabledStorageId,
-      preferenceNotifier: _legacyInspectorEnabled,
-    );
-  }
-
   Future<void> _initAutoRefreshEnabled() async {
     await _updateAutoRefreshEnabled();
     _saveBooleanPreferenceChanges(
@@ -124,14 +88,6 @@
     );
   }
 
-  Future<void> _updateLegacyInspectorEnabled() async {
-    await _updateBooleanPreference(
-      preferenceStorageId: _legacyInspectorEnabledStorageId,
-      preferenceNotifier: _legacyInspectorEnabled,
-      defaultValue: false,
-    );
-  }
-
   Future<void> _updateAutoRefreshEnabled() async {
     await _updateBooleanPreference(
       preferenceStorageId: _autoRefreshEnabledStorageId,
@@ -164,31 +120,6 @@
     preferenceNotifier.value = preferenceValue == 'true';
   }
 
-  Future<void> _initDefaultInspectorDetailsView() async {
-    await _updateInspectorDetailsViewSelection();
-
-    addAutoDisposeListener(_defaultDetailsView, () {
-      safeUnawaited(
-        storage.setValue(
-          _defaultDetailsViewStorageId,
-          _defaultDetailsView.value.name.toString(),
-        ),
-      );
-    });
-  }
-
-  Future<void> _updateInspectorDetailsViewSelection() async {
-    final inspectorDetailsView = await storage.getValue(
-      _defaultDetailsViewStorageId,
-    );
-
-    if (inspectorDetailsView != null) {
-      _defaultDetailsView.value = InspectorDetailsViewType.values.firstWhere(
-        (e) => e.name.toString() == inspectorDetailsView,
-      );
-    }
-  }
-
   void _initPubRootDirectories() {
     addAutoDisposeListener(
       serviceConnection.serviceManager.connectedState,
@@ -245,9 +176,7 @@
     _checkedFlutterPubRoot = false;
     await _updateMainScriptRef();
     await _updateHoverEvalMode();
-    await _updateLegacyInspectorEnabled();
     await loadPubRootDirectories();
-    await _updateInspectorDetailsViewSelection();
   }
 
   Future<void> loadPubRootDirectories() async {
@@ -474,16 +403,7 @@
   }
 
   @visibleForTesting
-  void setLegacyInspectorEnabled(bool legacyInspectorEnabled) {
-    _legacyInspectorEnabled.value = legacyInspectorEnabled;
-  }
-
-  @visibleForTesting
   void setAutoRefreshEnabled(bool autoRefreshEnabled) {
     _autoRefreshEnabled.value = autoRefreshEnabled;
   }
-
-  void setDefaultInspectorDetailsView(InspectorDetailsViewType value) {
-    _defaultDetailsView.value = value;
-  }
 }
diff --git a/packages/devtools_app/lib/src/shared/ui/icons.dart b/packages/devtools_app/lib/src/shared/ui/icons.dart
index 9feaa28..979cf15 100644
--- a/packages/devtools_app/lib/src/shared/ui/icons.dart
+++ b/packages/devtools_app/lib/src/shared/ui/icons.dart
@@ -13,7 +13,7 @@
 import 'package:devtools_app_shared/ui.dart';
 import 'package:flutter/material.dart';
 
-import '../../screens/inspector/layout_explorer/ui/widgets_theme.dart';
+import '../../screens/inspector_v2/layout_explorer/ui/widgets_theme.dart';
 import 'colors.dart';
 
 class CustomIcon extends StatelessWidget {
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
index d4e8482..3a13606 100644
--- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
+++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -19,7 +19,8 @@
 
 ## Inspector updates
 
-TODO: Remove this section if there are not any updates.
+- Deleted the option to use the legacy inspector.
+  [#9782](https://github.com/flutter/devtools/pull/9782)
 
 ## Performance updates
 
diff --git a/packages/devtools_app/test/screens/inspector/diagnostics_test.dart b/packages/devtools_app/test/screens/inspector/diagnostics_test.dart
deleted file mode 100644
index 1e1bb3e..0000000
--- a/packages/devtools_app/test/screens/inspector/diagnostics_test.dart
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2022 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:convert';
-
-import 'package:devtools_app/devtools_app.dart';
-import 'package:devtools_app/src/shared/ui/utils.dart';
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:devtools_test/devtools_test.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-void main() {
-  group('DiagnosticsNodeDescription', () {
-    final renderObjectJson = jsonDecode('''
-        {
-          "properties": [
-            {
-              "description": "horizontal",
-              "name": "direction"
-            },
-            {
-              "description": "start",
-              "name": "mainAxisAlignment"
-            },
-            {
-              "description": "max",
-              "name": "mainAxisSize"
-            },
-            {
-              "description": "center",
-              "name": "crossAxisAlignment"
-            },
-            {
-              "description": "ltr",
-              "name": "textDirection"
-            },
-            {
-              "description": "down",
-              "name": "verticalDirection"
-            }
-          ]
-        }
-      ''');
-    setUp(() {
-      setGlobal(
-        DevToolsEnvironmentParameters,
-        ExternalDevToolsEnvironmentParameters(),
-      );
-      setGlobal(PreferencesController, PreferencesController());
-      setGlobal(IdeTheme, IdeTheme());
-      setGlobal(ServiceConnectionManager, FakeServiceConnectionManager());
-    });
-
-    group('hover eval', () {
-      final nodeJson = <String, Object?>{
-        'widgetRuntimeType': 'Row',
-        'renderObject': renderObjectJson,
-        'hasChildren': false,
-        'children': [],
-      };
-      final inspectorService = MockInspectorObjectGroupBase();
-      final diagnostic = RemoteDiagnosticsNode(
-        nodeJson,
-        inspectorService,
-        false,
-        null,
-      );
-      late DiagnosticsNodeDescription diagnosticsNodeDescription;
-
-      setUp(() {
-        preferences.inspector.setHoverEvalMode(true);
-        diagnosticsNodeDescription = DiagnosticsNodeDescription(diagnostic);
-      });
-
-      testWidgets('can be enabled from preferences', (
-        WidgetTester tester,
-      ) async {
-        await tester.pumpWidget(wrap(diagnosticsNodeDescription));
-
-        final hoverCardTooltip =
-            tester.widget(find.byType(HoverCardTooltip)) as HoverCardTooltip;
-        expect(hoverCardTooltip.enabled(), true);
-      });
-
-      testWidgets('can be disabled from preferences', (
-        WidgetTester tester,
-      ) async {
-        preferences.inspector.setHoverEvalMode(false);
-
-        await tester.pumpWidget(wrap(diagnosticsNodeDescription));
-
-        final hoverCardTooltip =
-            tester.widget(find.byType(HoverCardTooltip)) as HoverCardTooltip;
-        expect(hoverCardTooltip.enabled(), false);
-      });
-
-      testWidgets('disabled when inspector service not set', (
-        WidgetTester tester,
-      ) async {
-        final diagnosticWithoutService = RemoteDiagnosticsNode(
-          nodeJson,
-          null,
-          false,
-          null,
-        );
-        diagnosticsNodeDescription = DiagnosticsNodeDescription(
-          diagnosticWithoutService,
-        );
-
-        await tester.pumpWidget(wrap(diagnosticsNodeDescription));
-
-        final hoverCardTooltip =
-            tester.widget(find.byType(HoverCardTooltip)) as HoverCardTooltip;
-        expect(hoverCardTooltip.enabled(), false);
-      });
-    });
-
-    group('approximateNodeWidth', () {
-      const epsilon = 7.0;
-      testWidgets('property diagnostics node with name and description', (
-        WidgetTester tester,
-      ) async {
-        final nodeJson = <String, Object?>{
-          'widgetRuntimeType': 'Row',
-          'renderObject': renderObjectJson,
-          'hasChildren': false,
-          'children': [],
-          'description':
-              'this is a showname description, which will show up after the name',
-          'showName': true,
-          'name': 'THE NAME to be shown',
-        };
-        final diagnosticWithoutService = RemoteDiagnosticsNode(
-          nodeJson,
-          null,
-          true,
-          null,
-        );
-        final diagnosticsNodeDescription = DiagnosticsNodeDescription(
-          diagnosticWithoutService,
-        );
-
-        await tester.pumpWidget(wrap(diagnosticsNodeDescription));
-
-        final approximatedWidth =
-            DiagnosticsNodeDescription.approximateNodeWidth(
-              diagnosticWithoutService,
-            );
-
-        final diagnosticsNodeFind = find.byType(DiagnosticsNodeDescription);
-        // There are many rich texts, containg the name, and description.
-        final allRichTexts = find
-            .descendant(
-              of: diagnosticsNodeFind,
-              matching: find.byType(RichText),
-            )
-            .evaluate()
-            .map((e) => e.widget as RichText);
-        final measuredWidthOfAllRichTexts = allRichTexts.fold<double>(
-          0,
-          (previousValue, richText) =>
-              previousValue + calculateTextSpanWidth(richText.text as TextSpan),
-        );
-        expect(
-          approximatedWidth,
-          moreOrLessEquals(measuredWidthOfAllRichTexts, epsilon: epsilon),
-        );
-      });
-
-      testWidgets('diagnostics node with icon and description', (
-        WidgetTester tester,
-      ) async {
-        final nodeJson = <String, Object?>{
-          'widgetRuntimeType': 'Row',
-          'renderObject': renderObjectJson,
-          'hasChildren': false,
-          'description': 'This is the description',
-          'children': [],
-          'showName': false,
-        };
-        final diagnosticWithoutService = RemoteDiagnosticsNode(
-          nodeJson,
-          null,
-          false,
-          null,
-        );
-        final diagnosticsNodeDescription = DiagnosticsNodeDescription(
-          diagnosticWithoutService,
-        );
-
-        await tester.pumpWidget(wrap(diagnosticsNodeDescription));
-
-        final approximatedTextWidth =
-            DiagnosticsNodeDescription.approximateNodeWidth(
-              diagnosticWithoutService,
-            );
-
-        final diagnosticsNodeFind = find.byType(DiagnosticsNodeDescription);
-        // The icon is part of the clickable width, so we include it.
-        final measuredIconWidth = tester
-            .getSize(
-              find.descendant(
-                of: diagnosticsNodeFind,
-                matching: find.byType(AssetImageIcon),
-              ),
-            )
-            .width;
-
-        // There is only one rich text widget, containing the description.
-        final richTextWidget =
-            find
-                    .descendant(
-                      of: diagnosticsNodeFind,
-                      matching: find.byType(RichText),
-                    )
-                    .first
-                    .evaluate()
-                    .first
-                    .widget
-                as RichText;
-        final measuredTextWidth = calculateTextSpanWidth(
-          richTextWidget.text as TextSpan,
-        );
-
-        expect(
-          approximatedTextWidth,
-          moreOrLessEquals(
-            measuredTextWidth + measuredIconWidth,
-            epsilon: epsilon,
-          ),
-        );
-      });
-
-      testWidgets('error node with different fontSize', (
-        WidgetTester tester,
-      ) async {
-        // Nodes with normal levels default to using the default fontSize, so
-        // using an error level node allows us to test different font sizes.
-        final nodeJson = <String, Object?>{
-          'widgetRuntimeType': 'Row',
-          'renderObject': renderObjectJson,
-          'hasChildren': false,
-          'children': [],
-          'description':
-              'this is a showname description, which will show up after the name',
-          'showName': true,
-          'name': 'THE NAME to be shown',
-          'level': 'error',
-        };
-        final diagnosticWithoutService = RemoteDiagnosticsNode(
-          nodeJson,
-          null,
-          false,
-          null,
-        );
-
-        //Use a textStyle that is much larger than the normal style
-        const textStyle = TextStyle(fontSize: 24.0, fontFamily: 'Roboto');
-        final diagnosticsNodeDescription = DiagnosticsNodeDescription(
-          diagnosticWithoutService,
-          style: textStyle,
-        );
-
-        await tester.pumpWidget(wrap(diagnosticsNodeDescription));
-
-        final approximatedWidth =
-            DiagnosticsNodeDescription.approximateNodeWidth(
-              diagnosticWithoutService,
-            );
-
-        final diagnosticsNodeFind = find.byType(DiagnosticsNodeDescription);
-        // There are many rich texts, containg the name, and description.
-        final allRichTexts = find
-            .descendant(
-              of: diagnosticsNodeFind,
-              matching: find.byType(RichText),
-            )
-            .evaluate()
-            .map((e) => e.widget as RichText);
-
-        final measuredWidthOfAllRichTexts = allRichTexts.fold<double>(0, (
-          previousValue,
-          richText,
-        ) {
-          final originalTextSpan = richText.text as TextSpan;
-
-          return previousValue + calculateTextSpanWidth(originalTextSpan);
-        });
-
-        expect(
-          approximatedWidth,
-          moreOrLessEquals(measuredWidthOfAllRichTexts, epsilon: epsilon),
-        );
-      });
-    });
-  });
-}
diff --git a/packages/devtools_app/test/screens/inspector/inspector_error_navigator_test.dart b/packages/devtools_app/test/screens/inspector/inspector_error_navigator_test.dart
deleted file mode 100644
index b546faa..0000000
--- a/packages/devtools_app/test/screens/inspector/inspector_error_navigator_test.dart
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:collection';
-
-import 'package:devtools_app/devtools_app.dart';
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:devtools_test/devtools_test.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-void main() {
-  setUp(() {
-    setGlobal(ServiceConnectionManager, FakeServiceConnectionManager());
-    setGlobal(IdeTheme, IdeTheme());
-  });
-
-  group('Inspector Error Navigator', () {
-    Future<void> testNavigate(
-      WidgetTester tester, {
-      required IconData tapIcon,
-      required int errorCount,
-      int? startIndex,
-      int? expectedIndex,
-    }) async {
-      var index = startIndex;
-      final navigator = ErrorNavigator(
-        errorIndex: index,
-        errors: _generateErrors(errorCount),
-        onSelectError: (newIndex) => index = newIndex,
-      );
-
-      await tester.pumpWidget(wrap(navigator));
-      await tester.tap(find.byIcon(tapIcon));
-
-      expect(index, equals(expectedIndex));
-    }
-
-    testWidgets('shows count when no selection', (WidgetTester tester) async {
-      await tester.pumpWidget(
-        wrap(
-          ErrorNavigator(
-            errorIndex: null,
-            errors: _generateErrors(10),
-            onSelectError: (_) {},
-          ),
-        ),
-      );
-      expect(find.text('Errors: 10'), findsOneWidget);
-    });
-
-    testWidgets('shows x/y when selected error', (WidgetTester tester) async {
-      await tester.pumpWidget(
-        wrap(
-          ErrorNavigator(
-            errorIndex: 0,
-            errors: _generateErrors(10),
-            onSelectError: (_) {},
-          ),
-        ),
-      );
-      expect(find.text('Error 1/10'), findsOneWidget);
-    });
-
-    testWidgets(
-      'can navigate forwards',
-      // Intentionally unawaited.
-      // ignore: discarded_futures
-      (WidgetTester tester) => testNavigate(
-        tester,
-        tapIcon: Icons.keyboard_arrow_down,
-        errorCount: 10,
-        startIndex: 5,
-        expectedIndex: 6,
-      ),
-    );
-
-    testWidgets(
-      'can navigate backwards',
-      // Intentionally unawaited.
-      // ignore: discarded_futures
-      (WidgetTester tester) => testNavigate(
-        tester,
-        tapIcon: Icons.keyboard_arrow_up,
-        errorCount: 10,
-        startIndex: 5,
-        expectedIndex: 4,
-      ),
-    );
-
-    testWidgets(
-      'wraps forwards',
-      // Intentionally unawaited.
-      // ignore: discarded_futures
-      (WidgetTester tester) => testNavigate(
-        tester,
-        tapIcon: Icons.keyboard_arrow_down,
-        errorCount: 10,
-        startIndex: 9,
-        expectedIndex: 0,
-      ),
-    );
-
-    testWidgets(
-      'wraps backwards',
-      // Intentionally unawaited.
-      // ignore: discarded_futures
-      (WidgetTester tester) => testNavigate(
-        tester,
-        tapIcon: Icons.keyboard_arrow_up,
-        errorCount: 10,
-        startIndex: 0,
-        expectedIndex: 9,
-      ),
-    );
-  });
-}
-
-LinkedHashMap<String, InspectableWidgetError> _generateErrors(int count) =>
-    LinkedHashMap<String, InspectableWidgetError>.fromEntries(
-      List.generate(
-        count,
-        (index) => MapEntry(
-          'error-$index',
-          InspectableWidgetError('Error $index', 'error-$index'),
-        ),
-      ),
-    );
diff --git a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart
deleted file mode 100644
index 659959a..0000000
--- a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2020 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/devtools_app.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import '../../test_infra/flutter_test_driver.dart' show FlutterRunConfiguration;
-import '../../test_infra/flutter_test_environment.dart';
-import '../../test_infra/matchers/matchers.dart';
-
-// This is a bit conservative to ensure we do not get flakes due to
-// slow interactions with the VM Service. This delay could likely be
-// reduced to under 1 second without introducing flakes.
-const inspectorChangeSettleTime = Duration(seconds: 2);
-
-void main() {
-  const windowSize = Size(2600.0, 1200.0);
-  // We need to use real async in this test so we need to use this binding.
-  initializeLiveTestWidgetsFlutterBindingWithAssets();
-
-  late FlutterTestEnvironment env;
-
-  Future<void> resetInspectorSelection() async {
-    final service = serviceConnection.inspectorService;
-    if (env.reuseTestEnvironment) {
-      // Ensure the previous test did not set the selection on the device.
-      // TODO(jacobr): add a proper method to WidgetInspectorService that does
-      // this. setSelection currently ignores null selection requests which is
-      // a misfeature.
-      await service!.inspectorLibrary.eval(
-        'WidgetInspectorService.instance.selection.clear()',
-        isAlive: null,
-      );
-    }
-  }
-
-  setUp(() async {
-    await env.setupEnvironment();
-    setGlobal(BannerMessagesController, BannerMessagesController());
-    // Ensure the legacy inspector is enabled:
-    preferences.inspector.setLegacyInspectorEnabled(true);
-  });
-
-  group('screenshot tests', () {
-    setUpAll(() {
-      env = FlutterTestEnvironment(
-        const FlutterRunConfiguration(withDebugger: true),
-      );
-      env.afterEverySetup = resetInspectorSelection;
-    });
-
-    tearDownAll(() async {
-      await env.tearDownEnvironment(force: true);
-    });
-
-    testWidgetsWithWindowSize('navigation', windowSize, (
-      WidgetTester tester,
-    ) async {
-      await env.setupEnvironment();
-      expect(serviceConnection.serviceManager.service, equals(env.service));
-      expect(serviceConnection.serviceManager.isolateManager, isNotNull);
-
-      final screen = InspectorScreen();
-      await tester.pumpWidget(
-        wrapWithInspectorControllers(Builder(builder: screen.build)),
-      );
-      await tester.pump(const Duration(seconds: 1));
-      final InspectorScreenBodyState state = tester.state(
-        find.byType(InspectorScreenBody),
-      );
-      final controller = state.controller;
-      while (!controller.flutterAppFrameReady) {
-        await controller.maybeLoadUI();
-        await tester.pumpAndSettle();
-      }
-      // Give time for the initial animation to complete.
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_initial_load.png',
-        ),
-      );
-
-      // Click on the Center widget (row index #5)
-      await tester.tap(find.richText('Center'));
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_select_center.png',
-        ),
-      );
-
-      // Select the details tree.
-      await tester.tap(
-        find.text(InspectorDetailsViewType.widgetDetailsTree.key),
-      );
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_select_center_details_tree.png',
-        ),
-        // Implementation widgets from Flutter framework are not guaranteed to
-        // be stable.
-        skip: 'https://github.com/flutter/flutter/issues/172037',
-      );
-
-      // Select the RichText row.
-      await tester.tap(find.richText('RichText'));
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_richtext_selected.png',
-        ),
-        // Implementation widgets from Flutter framework are not guaranteed to
-        // be stable.
-        skip: 'https://github.com/flutter/flutter/issues/172037',
-      );
-
-      // Test hovering over the icon shown when a property has its default
-      // value.
-      // TODO(jacobr): support tooltips in the Flutter version of the inspector.
-      // https://github.com/flutter/devtools/issues/2570.
-      // For example, verify that the tooltip hovering over the default value
-      // icons is "Default value".
-      // Test selecting a widget.
-
-      // Two 'Scaffold's: a breadcrumb and an actual tree item
-      expect(find.richText('Scaffold'), findsNWidgets(2));
-      // select Scaffold widget in summary tree.
-      await tester.tap(find.richText('Scaffold').last);
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      // This tree is huge. If there is a change to package:flutter it may
-      // change. If this happens don't panic and rebaseline the golden.
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_scaffold_selected.png',
-        ),
-        // Implementation widgets from Flutter framework are not guaranteed to
-        // be stable.
-        skip: 'https://github.com/flutter/flutter/issues/172037',
-      );
-
-      // The important thing about this is that the details tree should scroll
-      // instead of re-rooting as the selected row is already visible in the
-      // details tree.
-      await tester.tap(find.richText('AnimatedPhysicalModel'));
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_animated_physical_model_selected.png',
-        ),
-        // Implementation widgets from Flutter framework are not guaranteed to
-        // be stable.
-        skip: 'https://github.com/flutter/flutter/issues/172037',
-      );
-
-      await env.tearDownEnvironment();
-    });
-
-    // TODO(jacobr): convert these tests to screenshot tests like the initial
-    // state test.
-    /*
-
-
-      // Intentionally trigger multiple quick navigate action to ensure that
-      // multiple quick navigation commands in a row do not trigger race
-      // conditions getting out of order updates from the server.
-      tree.navigateDown();
-      tree.navigateDown();
-      tree.navigateDown();
-      await detailsTree.nextUiFrame;
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▼[A]AppBar <-- selected\n'
-          '          [/icons/inspector/textArea.png]Text\n',
-        ),
-      );
-      // Make sure we don't go off the bottom of the tree.
-      tree.navigateDown();
-      tree.navigateDown();
-      tree.navigateDown();
-      tree.navigateDown();
-      tree.navigateDown();
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▼[A]AppBar\n'
-          '          [/icons/inspector/textArea.png]Text <-- selected\n',
-        ),
-      );
-      tree.navigateUp();
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▼[A]AppBar <-- selected\n'
-          '          [/icons/inspector/textArea.png]Text\n',
-        ),
-      );
-      tree.navigateLeft();
-      await detailsTree.nextUiFrame;
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▶[A]AppBar <-- selected\n',
-        ),
-      );
-      tree.navigateLeft();
-      // First navigate left goes to the parent.
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold <-- selected\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▶[A]AppBar\n',
-        ),
-      );
-      tree.navigateLeft();
-      // Next navigate left closes the parent.
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¶[S]Scaffold <-- selected\n',
-        ),
-      );
-
-      tree.navigateRight();
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold <-- selected\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▶[A]AppBar\n',
-        ),
-      );
-
-      // Node is already expanded so this is equivalent to navigate down.
-      tree.navigateRight();
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold\n'
-          '      ├───▼[C]Center <-- selected\n'
-          '      │     [/icons/inspector/textArea.png]Text\n'
-          '      └─▶[A]AppBar\n',
-        ),
-      );
-
-      await detailsTree.nextUiFrame;
-
-      // Make sure the details and main trees have not gotten out of sync.
-      expect(
-        detailsTree.toStringDeep(hidePropertyLines: true),
-        equalsIgnoringHashCodes('â–¼[C]Center <-- selected\n'
-            '└─▼[/icons/inspector/textArea.png]Text\n'
-            '  └─▼[/icons/inspector/textArea.png]RichText\n'),
-      );
-
-      await env.tearDownEnvironment();
-    });
-    */
-
-    // TODO(jacobr): uncomment hotReload test once the hot reload test is not
-    // flaky. https://github.com/flutter/devtools/issues/642
-    /*
-    test('hotReload', () async {
-      if (flutterVersion == '1.2.1') {
-        // This test can be flaky in Flutter 1.2.1 because of
-        // https://github.com/dart-lang/sdk/issues/33838
-        // so we just skip it. This block of code can be removed after the next
-        // stable flutter release.
-        // TODO(dantup): Remove this.
-        return;
-      }
-      await env.setupEnvironment();
-
-      await serviceManager.performHotReload();
-      // Ensure the inspector does not fall over and die after a hot reload.
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-          '  â–¼[M]MyApp\n'
-          '    â–¼[M]MaterialApp\n'
-          '      â–¼[S]Scaffold\n'
-          '      ├───▼[C]Center\n'
-          '      │     [/icons/inspector/textArea.png]Text <-- selected\n'
-          '      └─▼[A]AppBar\n'
-          '          [/icons/inspector/textArea.png]Text\n',
-        ),
-      );
-
-      // TODO(jacobr): would be nice to have some tests that trigger a hot
-      // reload that actually changes app state in a meaningful way.
-
-      await env.tearDownEnvironment();
-    });
-    */
-    // TODO(jacobr): uncomment out the hotRestart tests once
-    // https://github.com/flutter/devtools/issues/337 is fixed.
-    /*
-    test('hotRestart', () async {
-      await env.setupEnvironment();
-
-      // The important thing about this is that the details tree should scroll
-      // instead of re-rooting as the selected row is already visible in the
-      // details tree.
-      simulateRowClick(tree, rowIndex: 4);
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R]root]\n'
-              '  â–¼[M]MyApp\n'
-              '    â–¼[M]MaterialApp\n'
-              '      â–¼[S]Scaffold\n'
-              '      ├───▼[C]Center <-- selected\n'
-              '      │     ▼[/icons/inspector/textArea.png]Text\n'
-              '      └─▼[A]AppBar\n'
-              '          â–¼[/icons/inspector/textArea.png]Text\n',
-        ),
-      );
-
-      /// After the hot restart some existing calls to the vm service may
-      /// timeout and that is ok.
-      serviceManager.manager.service.doNotWaitForPendingFuturesBeforeExit();
-
-      await serviceManager.performHotRestart();
-      // The isolate starts out paused on a hot restart so we have to resume
-      // it manually to make the test pass.
-
-      await serviceManager.manager.service
-          .resume(serviceManager.isolateManager.selectedIsolate.id);
-
-      // First UI transition is to an empty tree.
-      await detailsTree.nextUiFrame;
-      expect(tree.toStringDeep(), equalsIgnoringHashCodes('<empty>\n'));
-
-      // Notice that the selection has been lost due to the hot restart.
-      await detailsTree.nextUiFrame;
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-              '  â–¼[M]MyApp\n'
-              '    â–¼[M]MaterialApp\n'
-              '      â–¼[S]Scaffold\n'
-              '      ├───▼[C]Center\n'
-              '      │     ▼[/icons/inspector/textArea.png]Text\n'
-              '      └─▼[A]AppBar\n'
-              '          â–¼[/icons/inspector/textArea.png]Text\n',
-        ),
-      );
-
-      // Verify that the selection can actually be changed after a restart.
-      simulateRowClick(tree, rowIndex: 4);
-      expect(
-        tree.toStringDeep(),
-        equalsIgnoringHashCodes(
-          'â–¼[R][root]\n'
-              '  â–¼[M]MyApp\n'
-              '    â–¼[M]MaterialApp\n'
-              '      â–¼[S]Scaffold\n'
-              '      ├───▼[C]Center <-- selected\n'
-              '      │     ▼[/icons/inspector/textArea.png]Text\n'
-              '      └─▼[A]AppBar\n'
-              '          â–¼[/icons/inspector/textArea.png]Text\n',
-        ),
-      );
-      await env.tearDownEnvironment();
-    });
-*/
-  });
-
-  group('widget errors', () {
-    setUpAll(() async {
-      env = FlutterTestEnvironment(
-        testAppDirectory: 'test/test_infra/fixtures/inspector_app',
-        const FlutterRunConfiguration(withDebugger: true),
-      );
-      await env.setupEnvironment(
-        config: const FlutterRunConfiguration(
-          withDebugger: true,
-          entryScript: 'lib/overflow_errors.dart',
-        ),
-      );
-      env.afterEverySetup = resetInspectorSelection;
-      // Enable the legacy inspector.
-      preferences.inspector.setLegacyInspectorEnabled(true);
-    });
-
-    testWidgetsWithWindowSize('show navigator and error labels', windowSize, (
-      WidgetTester tester,
-    ) async {
-      expect(serviceConnection.serviceManager.service, equals(env.service));
-      expect(serviceConnection.serviceManager.isolateManager, isNotNull);
-
-      final screen = InspectorScreen();
-      await tester.pumpWidget(
-        wrapWithInspectorControllers(Builder(builder: screen.build)),
-      );
-      await tester.pumpAndSettle(const Duration(seconds: 1));
-      final InspectorScreenBodyState state = tester.state(
-        find.byType(InspectorScreenBody),
-      );
-      final controller = state.controller;
-      while (!controller.flutterAppFrameReady) {
-        await controller.maybeLoadUI();
-        await tester.pumpAndSettle();
-      }
-      await env.flutter!.hotReload();
-      // Give time for the initial animation to complete.
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_errors_1_initial_load.png',
-        ),
-      );
-
-      // Navigate so one of the errors is selected.
-      for (var i = 0; i < 2; i++) {
-        await tester.tap(find.byIcon(Icons.keyboard_arrow_down));
-        await tester.pumpAndSettle(inspectorChangeSettleTime);
-      }
-      await expectLater(
-        find.byType(InspectorScreenBody),
-        matchesDevToolsGolden(
-          '../../test_infra/goldens/integration_inspector_errors_2_error_selected.png',
-        ),
-      );
-
-      await env.tearDownEnvironment();
-    });
-  });
-}
diff --git a/packages/devtools_app/test/screens/inspector/inspector_screen_test.dart b/packages/devtools_app/test/screens/inspector/inspector_screen_test.dart
deleted file mode 100644
index 0a09554..0000000
--- a/packages/devtools_app/test/screens/inspector/inspector_screen_test.dart
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-// Fake construction requires number of unawaited calls.
-// ignore_for_file: discarded_futures
-
-import 'dart:convert';
-
-import 'package:devtools_app/devtools_app.dart';
-import 'package:devtools_app/src/screens/inspector/layout_explorer/flex/flex.dart';
-import 'package:devtools_app/src/screens/inspector/layout_explorer/layout_explorer.dart';
-import 'package:devtools_app/src/screens/inspector_shared/inspector_settings_dialog.dart';
-import 'package:devtools_app/src/service/service_extensions.dart' as extensions;
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:devtools_test/devtools_test.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart' hide Fake;
-import 'package:mockito/mockito.dart';
-
-import '../../test_infra/flutter_test_storage.dart';
-
-void main() {
-  final screen = InspectorScreen();
-
-  late FakeServiceConnectionManager fakeServiceConnection;
-  late FakeServiceExtensionManager fakeExtensionManager;
-  const windowSize = Size(2600.0, 1200.0);
-
-  final debuggerController = createMockDebuggerControllerWithDefaults();
-
-  Widget buildInspectorScreen() {
-    return wrapWithControllers(
-      Builder(builder: screen.build),
-      debugger: debuggerController,
-      inspector: InspectorScreenController(),
-    );
-  }
-
-  setUp(() {
-    fakeServiceConnection = FakeServiceConnectionManager();
-    fakeExtensionManager =
-        fakeServiceConnection.serviceManager.serviceExtensionManager;
-    mockConnectedApp(fakeServiceConnection.serviceManager.connectedApp!);
-    when(
-      fakeServiceConnection.errorBadgeManager.errorCountNotifier('inspector'),
-    ).thenReturn(ValueNotifier<int>(0));
-
-    setGlobal(
-      DevToolsEnvironmentParameters,
-      ExternalDevToolsEnvironmentParameters(),
-    );
-    setGlobal(ServiceConnectionManager, fakeServiceConnection);
-    setGlobal(IdeTheme, IdeTheme());
-    setGlobal(PreferencesController, PreferencesController());
-    setGlobal(Storage, FlutterTestStorage());
-    setGlobal(NotificationService, NotificationService());
-    setGlobal(BannerMessagesController, BannerMessagesController());
-    fakeServiceConnection.consoleService.ensureServiceInitialized();
-    // Enable the legacy inspector:
-    preferences.inspector.setLegacyInspectorEnabled(true);
-  });
-
-  Future<void> mockExtensions() async {
-    fakeExtensionManager.extensionValueOnDevice = {
-      extensions.toggleSelectWidgetMode.extension: true,
-      extensions.enableOnDeviceInspector.extension: true,
-      extensions.toggleOnDeviceWidgetInspector.extension: true,
-      extensions.debugPaint.extension: false,
-    };
-    await fakeExtensionManager.fakeAddServiceExtension(
-      extensions.toggleOnDeviceWidgetInspector.extension,
-    );
-    await fakeExtensionManager.fakeAddServiceExtension(
-      extensions.toggleSelectWidgetMode.extension,
-    );
-    await fakeExtensionManager.fakeAddServiceExtension(
-      extensions.enableOnDeviceInspector.extension,
-    );
-    await fakeExtensionManager.fakeAddServiceExtension(
-      extensions.debugPaint.extension,
-    );
-    await fakeExtensionManager.fakeFrame();
-  }
-
-  void mockNoExtensionsAvailable() {
-    fakeExtensionManager.extensionValueOnDevice = {
-      extensions.toggleOnDeviceWidgetInspector.extension: true,
-      extensions.toggleSelectWidgetMode.extension: false,
-      extensions.debugPaint.extension: false,
-    };
-    // Don't actually send any events to the client indicating that service
-    // extensions are avaiable.
-    fakeExtensionManager.fakeFrame();
-  }
-
-  testWidgetsWithWindowSize('builds its tab', windowSize, (
-    WidgetTester tester,
-  ) async {
-    await tester.pumpWidget(buildInspectorScreen());
-    await tester.pumpAndSettle();
-    expect(find.byType(InspectorScreenBody), findsOneWidget);
-  });
-
-  group('Widget Errors', () {
-    // Display of error navigator/indicators is tested by a golden in
-    // inspector_integration_test.dart
-
-    testWidgetsWithWindowSize(
-      'does not render error navigator if no errors',
-      windowSize,
-      (WidgetTester tester) async {
-        await tester.pumpWidget(buildInspectorScreen());
-        expect(find.byType(ErrorNavigator), findsNothing);
-      },
-    );
-  });
-
-  testWidgetsWithWindowSize('builds with no data', windowSize, (
-    WidgetTester tester,
-  ) async {
-    // Make sure the window is wide enough to display description text.
-
-    await tester.pumpWidget(buildInspectorScreen());
-    expect(find.byType(InspectorScreenBody), findsOneWidget);
-    expect(find.byTooltip('Refresh Tree'), findsOneWidget);
-    expect(find.text(extensions.debugPaint.title), findsOneWidget);
-    // Make sure there is not an overflow if the window is narrow.
-    // TODO(jacobr): determine why there are overflows in the test environment
-    // but not on the actual device for this cae.
-    // await setWindowSize(const Size(1000.0, 1200.0));
-    // Verify that description text is no-longer shown.
-    // expect(find.text(extensions.debugPaint.description), findsOneWidget);
-  });
-
-  testWidgetsWithWindowSize(
-    'Test toggling service extension buttons',
-    windowSize,
-    (WidgetTester tester) async {
-      await mockExtensions();
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .debugPaint
-            .extension],
-        isFalse,
-      );
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleOnDeviceWidgetInspector
-            .extension],
-        isTrue,
-      );
-
-      await tester.pumpWidget(buildInspectorScreen());
-
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleSelectWidgetMode
-            .extension],
-        isTrue,
-      );
-
-      // We need a frame to find out that the service extension state has changed.
-      expect(find.byType(InspectorScreenBody), findsOneWidget);
-      expect(
-        find.text(extensions.toggleSelectWidgetMode.title),
-        findsOneWidget,
-      );
-      expect(find.text(extensions.debugPaint.title), findsOneWidget);
-      await tester.pump();
-      await tester.tap(find.text(extensions.toggleSelectWidgetMode.title));
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleSelectWidgetMode
-            .extension],
-        isFalse,
-      );
-      // Verify the other service extension's state hasn't changed.
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .debugPaint
-            .extension],
-        isFalse,
-      );
-
-      await tester.tap(find.text(extensions.toggleSelectWidgetMode.title));
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleSelectWidgetMode
-            .extension],
-        isTrue,
-      );
-
-      await tester.tap(find.text(extensions.debugPaint.title));
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .debugPaint
-            .extension],
-        isTrue,
-      );
-    },
-  );
-
-  testWidgetsWithWindowSize(
-    'Test toggling service extension buttons with no extensions available',
-    windowSize,
-    (WidgetTester tester) async {
-      mockNoExtensionsAvailable();
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .debugPaint
-            .extension],
-        isFalse,
-      );
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleOnDeviceWidgetInspector
-            .extension],
-        isTrue,
-      );
-
-      await tester.pumpWidget(buildInspectorScreen());
-      await tester.pump();
-      expect(find.byType(InspectorScreenBody), findsOneWidget);
-      expect(
-        find.text(extensions.toggleOnDeviceWidgetInspector.title),
-        findsOneWidget,
-      );
-      expect(find.text(extensions.debugPaint.title), findsOneWidget);
-      await tester.pump();
-
-      await tester.tap(
-        find.text(extensions.toggleOnDeviceWidgetInspector.title),
-      );
-      // Verify the service extension state has not changed.
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleOnDeviceWidgetInspector
-            .extension],
-        isTrue,
-      );
-      await tester.tap(
-        find.text(extensions.toggleOnDeviceWidgetInspector.title),
-      );
-      // Verify the service extension state has not changed.
-      expect(
-        fakeExtensionManager.extensionValueOnDevice[extensions
-            .toggleOnDeviceWidgetInspector
-            .extension],
-        isTrue,
-      );
-
-      // TODO(jacobr): also verify that the service extension buttons look
-      // visually disabled.
-    },
-  );
-
-  group('LayoutDetailsTab', () {
-    final renderObjectJson = jsonDecode('''
-        {
-          "properties": [
-            {
-              "description": "horizontal",
-              "name": "direction"
-            },
-            {
-              "description": "start",
-              "name": "mainAxisAlignment"
-            },
-            {
-              "description": "max",
-              "name": "mainAxisSize"
-            },
-            {
-              "description": "center",
-              "name": "crossAxisAlignment"
-            },
-            {
-              "description": "ltr",
-              "name": "textDirection"
-            },
-            {
-              "description": "down",
-              "name": "verticalDirection"
-            }
-          ]
-        }
-      ''');
-    final diagnostic = RemoteDiagnosticsNode(
-      <String, Object?>{
-        'widgetRuntimeType': 'Row',
-        'renderObject': renderObjectJson,
-        'hasChildren': false,
-        'children': [],
-      },
-      null,
-      false,
-      null,
-    );
-    final treeNode = InspectorTreeNode()..diagnostic = diagnostic;
-    testWidgetsWithWindowSize(
-      'should render StoryOfYourFlexWidget',
-      windowSize,
-      (WidgetTester tester) async {
-        final controller = TestInspectorController()..setSelectedNode(treeNode);
-        await tester.pumpWidget(
-          MaterialApp(
-            home: Scaffold(body: LayoutExplorerTab(controller: controller)),
-          ),
-        );
-        expect(find.byType(FlexLayoutExplorerWidget), findsOneWidget);
-      },
-    );
-
-    testWidgetsWithWindowSize(
-      'should listen to controller selection event',
-      windowSize,
-      (WidgetTester tester) async {
-        final controller = TestInspectorController();
-        await tester.pumpWidget(
-          MaterialApp(
-            home: Scaffold(body: LayoutExplorerTab(controller: controller)),
-          ),
-        );
-        expect(find.byType(FlexLayoutExplorerWidget), findsNothing);
-        controller.setSelectedNode(treeNode);
-        await tester.pumpAndSettle();
-        expect(find.byType(FlexLayoutExplorerWidget), findsOneWidget);
-      },
-    );
-  });
-
-  group('FlutterInspectorSettingsDialog', () {
-    const startingHoverEvalModeValue = false;
-
-    setUp(() {
-      preferences.inspector.setHoverEvalMode(startingHoverEvalModeValue);
-    });
-
-    testWidgetsWithWindowSize(
-      'can update hover inspection setting',
-      windowSize,
-      (WidgetTester tester) async {
-        await tester.pumpWidget(buildInspectorScreen());
-
-        await tester.tap(find.byType(SettingsOutlinedButton));
-        await tester.pumpAndSettle();
-        expect(find.byType(FlutterInspectorSettingsDialog), findsOneWidget);
-
-        final hoverCheckBoxSetting = find.ancestor(
-          of: find.richTextContaining('Enable hover inspection'),
-          matching: find.byType(CheckboxSetting),
-        );
-        final hoverModeCheckBox = find.descendant(
-          of: hoverCheckBoxSetting,
-          matching: find.byType(NotifierCheckbox),
-        );
-        await tester.tap(hoverModeCheckBox);
-        await tester.pumpAndSettle();
-        expect(
-          preferences.inspector.hoverEvalModeEnabled.value,
-          !startingHoverEvalModeValue,
-        );
-      },
-    );
-  });
-
-  // TODO(jacobr): add screenshot tests that connect to a test application
-  // in the same way the inspector_controller test does today and take golden
-  // images. Alternately: support an offline inspector mode and add tests of
-  // that mode which would enable faster tests that run as unittests.
-}
diff --git a/packages/devtools_app/test/screens/inspector/inspector_tree_test.dart b/packages/devtools_app/test/screens/inspector/inspector_tree_test.dart
deleted file mode 100644
index 17d1b12..0000000
--- a/packages/devtools_app/test/screens/inspector/inspector_tree_test.dart
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/devtools_app.dart';
-import 'package:devtools_app/src/screens/inspector/inspector_breadcrumbs.dart';
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:devtools_test/devtools_test.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart' hide Fake;
-import 'package:mockito/mockito.dart';
-
-import 'utils/inspector_tree.dart';
-
-void main() {
-  late FakeServiceConnectionManager fakeServiceConnection;
-  late InspectorController inspectorController;
-
-  setUp(() {
-    fakeServiceConnection = FakeServiceConnectionManager();
-    final app = fakeServiceConnection.serviceManager.connectedApp!;
-    when(app.isFlutterAppNow).thenReturn(true);
-    when(app.isProfileBuildNow).thenReturn(false);
-
-    setGlobal(
-      DevToolsEnvironmentParameters,
-      ExternalDevToolsEnvironmentParameters(),
-    );
-    setGlobal(ServiceConnectionManager, fakeServiceConnection);
-    setGlobal(IdeTheme, IdeTheme());
-    setGlobal(PreferencesController, PreferencesController());
-    setGlobal(NotificationService, NotificationService());
-    setGlobal(BreakpointManager, BreakpointManager());
-    mockConnectedApp(fakeServiceConnection.serviceManager.connectedApp!);
-
-    inspectorController = InspectorController(
-      inspectorTree: InspectorTreeController(),
-      detailsTree: InspectorTreeController(),
-      treeType: FlutterTreeType.widget,
-    )..firstInspectorTreeLoadCompleted = true;
-  });
-
-  Future<void> pumpInspectorTree(
-    WidgetTester tester, {
-    required InspectorTreeController treeController,
-    bool isSummaryTree = false,
-  }) async {
-    final debuggerController = DebuggerController();
-    final summaryTreeController = isSummaryTree
-        ? null
-        : InspectorTreeController();
-    await tester.pumpWidget(
-      wrapWithControllers(
-        debugger: debuggerController,
-        InspectorTree(
-          controller: inspectorController,
-          treeController: treeController,
-          summaryTreeController: summaryTreeController,
-          isSummaryTree: isSummaryTree,
-        ),
-      ),
-    );
-    await tester.pumpAndSettle();
-  }
-
-  group('InspectorTreeController', () {
-    testWidgets('Row with negative index regression test', (
-      WidgetTester tester,
-    ) async {
-      final treeController = InspectorTreeController()
-        ..config = InspectorTreeConfig(
-          onNodeAdded: (_, _) {},
-          onClientActiveChange: (_) {},
-        );
-      await pumpInspectorTree(tester, treeController: treeController);
-
-      expect(treeController.getRow(const Offset(0, -100.0)), isNull);
-      expect(treeController.getRowOffset(-1), equals(0));
-
-      expect(treeController.getRow(const Offset(0, 0.0)), isNull);
-      expect(treeController.getRowOffset(0), equals(0));
-
-      treeController.root = InspectorTreeNode()
-        ..appendChild(InspectorTreeNode());
-
-      await pumpInspectorTree(tester, treeController: treeController);
-
-      expect(treeController.getRow(const Offset(0, -20))!.index, 0);
-      expect(treeController.getRowOffset(-1), equals(0));
-      expect(treeController.getRow(const Offset(0, 0.0)), isNotNull);
-      expect(treeController.getRowOffset(0), equals(0));
-
-      // This operation would previously throw an exception in debug builds
-      // and infinite loop in release builds.
-      treeController.scrollToRect(const Rect.fromLTWH(0, -20, 100, 100));
-    });
-  });
-
-  group('Inspector tree content preview', () {
-    testWidgets('Shows simple text preview', (WidgetTester tester) async {
-      final diagnosticNode = await widgetToInspectorTreeDiagnosticsNode(
-        widget: const Text('Content'),
-        tester: tester,
-      );
-
-      final treeController = inspectorTreeControllerFromNode(diagnosticNode);
-      await pumpInspectorTree(tester, treeController: treeController);
-
-      expect(find.richText('Text: "Content"'), findsOneWidget);
-    });
-
-    testWidgets('Shows preview from Text.rich', (WidgetTester tester) async {
-      final diagnosticNode = await widgetToInspectorTreeDiagnosticsNode(
-        widget: const Text.rich(
-          TextSpan(
-            children: [
-              TextSpan(text: 'Rich '),
-              TextSpan(text: 'text'),
-            ],
-          ),
-        ),
-        tester: tester,
-      );
-
-      final treeController = inspectorTreeControllerFromNode(diagnosticNode);
-      await pumpInspectorTree(tester, treeController: treeController);
-
-      expect(find.richText('Text: "Rich text"'), findsOneWidget);
-    });
-
-    testWidgets('Strips new lines from text preview', (
-      WidgetTester tester,
-    ) async {
-      final diagnosticNode = await widgetToInspectorTreeDiagnosticsNode(
-        widget: const Text('Multiline\ntext\n\ncontent'),
-        tester: tester,
-      );
-
-      final treeController = inspectorTreeControllerFromNode(diagnosticNode);
-      await pumpInspectorTree(tester, treeController: treeController);
-
-      expect(find.richText('Text: "Multiline text  content"'), findsOneWidget);
-    });
-
-    testWidgets('Shows breadcrumbs in Widget detail tree', (tester) async {
-      final diagnosticNode = await widgetToInspectorTreeDiagnosticsNode(
-        widget: const Text('Hello'),
-        tester: tester,
-      );
-
-      final treeController = inspectorTreeControllerFromNode(diagnosticNode);
-      await pumpInspectorTree(tester, treeController: treeController);
-
-      expect(find.byType(InspectorBreadcrumbNavigator), findsOneWidget);
-    });
-
-    testWidgets('Shows no breadcrumbs widget in summary tree', (tester) async {
-      final diagnosticNode = await widgetToInspectorTreeDiagnosticsNode(
-        widget: const Text('Hello'),
-        tester: tester,
-      );
-
-      final treeController = inspectorTreeControllerFromNode(diagnosticNode);
-      await pumpInspectorTree(
-        tester,
-        treeController: treeController,
-        isSummaryTree: true,
-      );
-
-      expect(find.byType(InspectorBreadcrumbNavigator), findsNothing);
-    });
-  });
-}
diff --git a/packages/devtools_app/test/screens/inspector/layout_explorer/flex/arrow_test.dart b/packages/devtools_app/test/screens/inspector/layout_explorer/flex/arrow_test.dart
deleted file mode 100644
index 2b5bf8c..0000000
--- a/packages/devtools_app/test/screens/inspector/layout_explorer/flex/arrow_test.dart
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/src/screens/inspector/layout_explorer/ui/arrow.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import '../../../../test_infra/matchers/matchers.dart';
-
-void main() {
-  const relativeGoldenPath =
-      '../../../../test_infra/goldens/inspector/layout_explorer/flex';
-
-  group('Arrow Golden Tests', () {
-    group('Unidirectional', () {
-      Widget buildUnidirectionalArrowWrapper(ArrowType type) => Directionality(
-        textDirection: TextDirection.ltr,
-        child: SizedBox(
-          width: 100,
-          height: 100,
-          child: ArrowWrapper.unidirectional(
-            type: type,
-            arrowColor: Colors.black,
-            arrowHeadSize: 8.0,
-            child: Container(width: 10, height: 10, color: Colors.red),
-          ),
-        ),
-      );
-      testWidgets('left', (WidgetTester tester) async {
-        final widget = buildUnidirectionalArrowWrapper(ArrowType.left);
-        await tester.pumpWidget(widget);
-        await expectLater(
-          find.byWidget(widget),
-          matchesDevToolsGolden(
-            '$relativeGoldenPath/arrow_unidirectional_left.png',
-          ),
-        );
-      }, skip: kIsWeb);
-      testWidgets('up', (WidgetTester tester) async {
-        final widget = buildUnidirectionalArrowWrapper(ArrowType.up);
-        await tester.pumpWidget(widget);
-        await expectLater(
-          find.byWidget(widget),
-          matchesDevToolsGolden(
-            '$relativeGoldenPath/arrow_unidirectional_up.png',
-          ),
-        );
-      }, skip: kIsWeb);
-      testWidgets('right', (WidgetTester tester) async {
-        final widget = buildUnidirectionalArrowWrapper(ArrowType.right);
-        await tester.pumpWidget(widget);
-        await expectLater(
-          find.byWidget(widget),
-          matchesDevToolsGolden(
-            '$relativeGoldenPath/arrow_unidirectional_right.png',
-          ),
-        );
-      }, skip: kIsWeb);
-      testWidgets('down', (WidgetTester tester) async {
-        final widget = buildUnidirectionalArrowWrapper(ArrowType.down);
-        await tester.pumpWidget(widget);
-        await expectLater(
-          find.byWidget(widget),
-          matchesDevToolsGolden(
-            '$relativeGoldenPath/arrow_unidirectional_down.png',
-          ),
-        );
-      }, skip: kIsWeb);
-    });
-
-    group('Bidirectional', () {
-      Widget buildBidirectionalArrowWrapper(Axis direction) => Directionality(
-        textDirection: TextDirection.ltr,
-        child: SizedBox(
-          width: 100,
-          height: 100,
-          child: ArrowWrapper.bidirectional(
-            direction: direction,
-            arrowColor: Colors.black,
-            arrowHeadSize: 8.0,
-            child: Container(width: 10, height: 10, color: Colors.red),
-          ),
-        ),
-      );
-      testWidgets('horizontal', (WidgetTester tester) async {
-        final widget = buildBidirectionalArrowWrapper(Axis.horizontal);
-        await tester.pumpWidget(widget);
-        await expectLater(
-          find.byWidget(widget),
-          matchesDevToolsGolden(
-            '$relativeGoldenPath/arrow_bidirectional_horizontal.png',
-          ),
-        );
-      }, skip: kIsWeb);
-      testWidgets('vertical', (WidgetTester tester) async {
-        final widget = buildBidirectionalArrowWrapper(Axis.vertical);
-        await tester.pumpWidget(widget);
-        await expectLater(
-          find.byWidget(widget),
-          matchesDevToolsGolden(
-            '$relativeGoldenPath/arrow_bidirectional_vertical.png',
-          ),
-        );
-      }, skip: kIsWeb);
-    });
-  });
-}
diff --git a/packages/devtools_app/test/screens/inspector/layout_explorer/flex/flex_test.dart b/packages/devtools_app/test/screens/inspector/layout_explorer/flex/flex_test.dart
deleted file mode 100644
index a8b5264..0000000
--- a/packages/devtools_app/test/screens/inspector/layout_explorer/flex/flex_test.dart
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'dart:convert';
-
-import 'package:devtools_app/src/screens/inspector/layout_explorer/flex/flex.dart';
-import 'package:devtools_app/src/shared/console/eval/inspector_tree.dart';
-import 'package:devtools_app/src/shared/diagnostics/diagnostics_node.dart';
-import 'package:devtools_test/devtools_test.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import '../../../../test_infra/matchers/matchers.dart';
-
-// TODO(albertusangga): Re-enable tests in this files
-// https://github.com/flutter/devtools/issues/1403
-void main() {
-  const windowSize = Size(1750, 1750);
-  const relativeGoldenPath =
-      '../../../../test_infra/goldens/inspector/layout_explorer/flex';
-
-  Map<String, Object> buildDiagnosticsNodeJson(Axis axis) => jsonDecode('''
-      {
-        "description": "${axis == Axis.horizontal ? 'Row' : 'Column'}",
-        "type": "_ElementDiagnosticableTreeNode",
-        "style": "dense",
-        "hasChildren": true,
-        "allowWrap": false,
-        "objectId": "inspector-267513",
-        "valueId": "inspector-251",
-        "summaryTree": true,
-        "constraints": {
-            "type": "BoxConstraints",
-            "description": "BoxConstraints(w=300.0, h=60.0)",
-            "minWidth": "300.0",
-            "minHeight": "60.0",
-            "maxHeight": "60.0",
-            "maxWidth": "300.0"
-        },
-        "size": {
-            "width": "300.0",
-            "height": "60.0"
-        },
-        "isFlex": true,
-        "children": [
-            {
-                "description": "Container",
-                "type": "_ElementDiagnosticableTreeNode",
-                "style": "dense",
-                "hasChildren": true,
-                "allowWrap": false,
-                "objectId": "inspector-267524",
-                "valueId": "inspector-269",
-                "summaryTree": true,
-                "constraints": {
-                    "type": "BoxConstraints",
-                    "description": "BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=56.0)",
-                    "minWidth": "0.0",
-                    "minHeight": "0.0",
-                    "maxHeight": "56.0",
-                    "maxWidth": "Infinity"
-                },
-                "size": {
-                    "width": "56.0",
-                    "height": "25.0"
-                },
-                "flexFactor": null,
-                "createdByLocalProject": true,
-                "children": [],
-                "widgetRuntimeType": "Container",
-                "stateful": false
-            },
-            {
-                "description": "Expanded",
-                "type": "_ElementDiagnosticableTreeNode",
-                "style": "dense",
-                "hasChildren": true,
-                "allowWrap": false,
-                "objectId": "inspector-267563",
-                "valueId": "inspector-332",
-                "summaryTree": true,
-                "constraints": {
-                    "type": "BoxConstraints",
-                    "description": "BoxConstraints(w=40.0, 0.0<=h<=56.0)",
-                    "minWidth": "40.0",
-                    "minHeight": "0.0",
-                    "maxHeight": "56.0",
-                    "maxWidth": "40.0"
-                },
-                "size": {
-                    "width": "40.0",
-                    "height": "31.0"
-                },
-                "flexFactor": 1,
-                "createdByLocalProject": true,
-                "children": [],
-                "widgetRuntimeType": "Expanded"
-            }
-        ],
-        "widgetRuntimeType": "${axis == Axis.horizontal ? 'Row' : 'Column'}",
-        "renderObject": {
-        "description": "RenderFlex#6cfb1 relayoutBoundary=up5",
-        "type": "DiagnosticableTreeNode",
-        "hasChildren": true,
-        "allowWrap": false,
-        "objectId": "inspector-3758",
-        "valueId": "inspector-118",
-        "summaryTree": true,
-        "properties": [
-          {
-            "description": "<none> (can use size)",
-            "type": "DiagnosticsProperty<ParentData>",
-            "name": "parentData",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3759",
-            "valueId": "inspector-120",
-            "summaryTree": true,
-            "properties": [],
-            "ifNull": "MISSING",
-            "tooltip": "can use size",
-            "missingIfNull": true,
-            "propertyType": "ParentData",
-            "defaultLevel": "info"
-          },
-          {
-            "description": "${axis.name}",
-            "type": "EnumProperty<Axis>",
-            "name": "direction",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3762",
-            "valueId": "inspector-126",
-            "summaryTree": true,
-            "properties": [],
-            "missingIfNull": false,
-            "propertyType": "Axis",
-            "defaultLevel": "info"
-          },
-          {
-            "description": "start",
-            "type": "EnumProperty<MainAxisAlignment>",
-            "name": "mainAxisAlignment",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3763",
-            "valueId": "inspector-128",
-            "summaryTree": true,
-            "properties": [],
-            "missingIfNull": false,
-            "propertyType": "MainAxisAlignment",
-            "defaultLevel": "info"
-          },
-          {
-            "description": "max",
-            "type": "EnumProperty<MainAxisSize>",
-            "name": "mainAxisSize",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3764",
-            "valueId": "inspector-130",
-            "summaryTree": true,
-            "properties": [],
-            "missingIfNull": false,
-            "propertyType": "MainAxisSize",
-            "defaultLevel": "info"
-          },
-          {
-            "description": "center",
-            "type": "EnumProperty<CrossAxisAlignment>",
-            "name": "crossAxisAlignment",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3765",
-            "valueId": "inspector-132",
-            "summaryTree": true,
-            "properties": [],
-            "missingIfNull": false,
-            "propertyType": "CrossAxisAlignment",
-            "defaultLevel": "info"
-          },
-          {
-            "description": "ltr",
-            "type": "EnumProperty<TextDirection>",
-            "name": "textDirection",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3766",
-            "valueId": "inspector-83",
-            "summaryTree": true,
-            "properties": [],
-            "defaultValue": "null",
-            "missingIfNull": false,
-            "propertyType": "TextDirection",
-            "defaultLevel": "info"
-          },
-          {
-            "description": "down",
-            "type": "EnumProperty<VerticalDirection>",
-            "name": "verticalDirection",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3767",
-            "valueId": "inspector-135",
-            "summaryTree": true,
-            "properties": [],
-            "defaultValue": "null",
-            "missingIfNull": false,
-            "propertyType": "VerticalDirection",
-            "defaultLevel": "info"
-          },
-           {
-            "description": "alphabetic",
-            "type": "EnumProperty<TextBaseline>",
-            "name": "textBaseline",
-            "style": "singleLine",
-            "allowNameWrap": true,
-            "objectId": "inspector-3767",
-            "valueId": "inspector-135",
-            "summaryTree": true,
-            "properties": [],
-            "defaultValue": "null",
-            "missingIfNull": false,
-            "propertyType": "TextBaseline",
-            "defaultLevel": "info"
-          }
-        ]
-      }
-    }
-    ''');
-
-  Widget wrap(Widget widget) {
-    return MaterialApp(home: Scaffold(body: widget));
-  }
-
-  /// current workaround for flaky image asset testing.
-  /// https://github.com/flutter/flutter/issues/38997
-  Future<void> pump(WidgetTester tester, Widget w) async {
-    await tester.runAsync(() async {
-      await tester.pumpWidget(w);
-      for (final element in find.byType(Image).evaluate()) {
-        final widget = element.widget as Image;
-        final image = widget.image;
-        await precacheImage(image, element);
-        await tester.pumpAndSettle();
-      }
-    });
-  }
-
-  testWidgetsWithWindowSize('Row golden test', windowSize, (
-    WidgetTester tester,
-  ) async {
-    final rowWidgetJsonNode = buildDiagnosticsNodeJson(Axis.horizontal);
-    final diagnostic = RemoteDiagnosticsNode(
-      rowWidgetJsonNode,
-      null,
-      false,
-      null,
-    );
-    final treeNode = InspectorTreeNode()..diagnostic = diagnostic;
-    final controller = TestInspectorController()..setSelectedNode(treeNode);
-    final widget = wrap(FlexLayoutExplorerWidget(controller));
-    await pump(tester, widget);
-    await tester.pumpAndSettle();
-    await expectLater(
-      find.byWidget(widget),
-      matchesDevToolsGolden('$relativeGoldenPath/story_of_row_layout.png'),
-    );
-  }, skip: true);
-
-  testWidgetsWithWindowSize('Column golden test', windowSize, (
-    WidgetTester tester,
-  ) async {
-    final columnWidgetJsonNode = buildDiagnosticsNodeJson(Axis.vertical);
-    final diagnostic = RemoteDiagnosticsNode(
-      columnWidgetJsonNode,
-      null,
-      false,
-      null,
-    );
-    final treeNode = InspectorTreeNode()..diagnostic = diagnostic;
-    final controller = TestInspectorController()..setSelectedNode(treeNode);
-    final widget = wrap(FlexLayoutExplorerWidget(controller));
-    await pump(tester, widget);
-    await expectLater(
-      find.byWidget(widget),
-      matchesDevToolsGolden('$relativeGoldenPath/story_of_column_layout.png'),
-    );
-  }, skip: true);
-}
diff --git a/packages/devtools_app/test/screens/inspector/layout_explorer/inspector_data_models_test.dart b/packages/devtools_app/test/screens/inspector/layout_explorer/inspector_data_models_test.dart
deleted file mode 100644
index a8e0cd0..0000000
--- a/packages/devtools_app/test/screens/inspector/layout_explorer/inspector_data_models_test.dart
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2019 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/src/screens/inspector/inspector_data_models.dart';
-import 'package:devtools_app/src/screens/inspector/layout_explorer/ui/theme.dart';
-import 'package:devtools_app/src/shared/primitives/math_utils.dart';
-import 'package:devtools_app_shared/ui.dart';
-import 'package:devtools_app_shared/utils.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import 'layout_explorer_test_utils.dart';
-
-void main() {
-  setGlobal(IdeTheme, IdeTheme());
-
-  group('FlexLayoutProperties tests', () {
-    Future<FlexLayoutProperties> toFlexLayoutProperties(
-      Flex flex, {
-      required WidgetTester tester,
-      int subtreeDepth = 2,
-      double? width,
-      double? height,
-    }) async {
-      final wrappedWidget = SizedBox(width: width, height: height, child: flex);
-      final rootNodeDiagnostics =
-          await widgetToLayoutExplorerRemoteDiagnosticsNode(
-            widget: wrappedWidget,
-            tester: tester,
-            subtreeDepth: subtreeDepth,
-          );
-      final flexDiagnostics = rootNodeDiagnostics.childrenNow.first;
-      return FlexLayoutProperties.fromDiagnostics(flexDiagnostics);
-    }
-
-    testWidgets(
-      'FlexLayoutProperties.fromJson creates correct value from enum',
-      (tester) async {
-        const widget = Row(
-          textDirection: TextDirection.ltr,
-          children: [SizedBox()],
-        );
-        final flexProperties = await toFlexLayoutProperties(
-          widget,
-          tester: tester,
-        );
-        expect(flexProperties.direction, Axis.horizontal);
-        expect(flexProperties.mainAxisAlignment, MainAxisAlignment.start);
-        expect(flexProperties.mainAxisSize, MainAxisSize.max);
-        expect(flexProperties.crossAxisAlignment, CrossAxisAlignment.center);
-        expect(flexProperties.textDirection, TextDirection.ltr);
-        expect(flexProperties.verticalDirection, VerticalDirection.down);
-        expect(flexProperties.textBaseline, null);
-      },
-    );
-
-    testWidgets('startIsTopLeft should return false', (tester) async {
-      const columnWidget = Column(
-        verticalDirection: VerticalDirection.up,
-        children: [SizedBox()],
-      );
-      final columnProperties = await toFlexLayoutProperties(
-        columnWidget,
-        tester: tester,
-      );
-      expect(columnProperties.startIsTopLeft, false);
-
-      const rowWidget = Row(
-        textDirection: TextDirection.rtl,
-        children: [SizedBox()],
-      );
-      final rowProperties = await toFlexLayoutProperties(
-        rowWidget,
-        tester: tester,
-      );
-      expect(rowProperties.startIsTopLeft, false);
-    });
-
-    testWidgets(
-      'displayChildren is the same as children when start is top left',
-      (tester) async {
-        final widget = Column(children: [const SizedBox(), Container()]);
-        final properties = await toFlexLayoutProperties(widget, tester: tester);
-        expect(properties.startIsTopLeft, true);
-        expect(properties.displayChildren[0].description, 'SizedBox');
-        expect(properties.displayChildren[1].description, 'Container');
-      },
-    );
-
-    testWidgets(
-      'displayChildren is a reversed children when start is not top left',
-      (tester) async {
-        final widget = Column(
-          verticalDirection: VerticalDirection.up,
-          children: [const SizedBox(), Container()],
-        );
-        final properties = await toFlexLayoutProperties(widget, tester: tester);
-        expect(properties.startIsTopLeft, false);
-        expect(properties.displayChildren[0].description, 'Container');
-        expect(properties.displayChildren[1].description, 'SizedBox');
-      },
-    );
-
-    group('childrenRenderProperties tests', () {
-      const maxMainAxisDimension = 500.0;
-
-      double maxSizeAvailable(Axis _) => maxMainAxisDimension;
-
-      List<RenderProperties> childrenRenderProperties(
-        FlexLayoutProperties properties,
-      ) => properties.childrenRenderProperties(
-        smallestRenderWidth: minRenderWidth,
-        largestRenderWidth: defaultMaxRenderWidth,
-        smallestRenderHeight: minRenderHeight,
-        largestRenderHeight: defaultMaxRenderHeight,
-        maxSizeAvailable: maxSizeAvailable,
-      );
-
-      final childrenWidgets = <Widget>[
-        const SizedBox(width: 50.0),
-        const SizedBox(width: 75.0, height: 25.0),
-      ];
-
-      testWidgets(
-        'returns correct RenderProperties with main axis not flipped when start is top left',
-        (tester) async {
-          final widget = Row(children: childrenWidgets);
-          final properties = await toFlexLayoutProperties(
-            widget,
-            width: maxMainAxisDimension,
-            tester: tester,
-            subtreeDepth: 3,
-          );
-          final renderProps = properties.childrenRenderProperties(
-            smallestRenderWidth: minRenderWidth,
-            largestRenderWidth: defaultMaxRenderWidth,
-            smallestRenderHeight: minRenderHeight,
-            largestRenderHeight: defaultMaxRenderHeight,
-            maxSizeAvailable: maxSizeAvailable,
-          );
-          expect(renderProps.length, 3);
-          expect(renderProps, [
-            RenderProperties(
-              axis: Axis.horizontal,
-              size: const Size(250, 250),
-              realSize: const Size(50.0, 0.0),
-              offset: const Offset(0.0, 125.0),
-              layoutProperties: properties,
-            ),
-            RenderProperties(
-              axis: Axis.horizontal,
-              size: const Size(261.5, 500),
-              realSize: const Size(75.0, 25.0),
-              offset: const Offset(250.0, 0.0),
-              layoutProperties: properties,
-            ),
-            RenderProperties(
-              axis: Axis.horizontal,
-              size: const Size(400, 500),
-              realSize: const Size(375.0, 25.0),
-              offset: const Offset(511.5, 0.0),
-              isFreeSpace: true,
-              layoutProperties: properties,
-            ),
-          ]);
-        },
-      );
-
-      testWidgets(
-        'returns correct RenderProperties with main axis flipped when start is not top left',
-        (tester) async {
-          final widget = Row(
-            textDirection: TextDirection.rtl,
-            children: childrenWidgets,
-          );
-          final properties = await toFlexLayoutProperties(
-            widget,
-            tester: tester,
-            width: maxMainAxisDimension,
-            subtreeDepth: 3,
-          );
-          final renderProps = properties.childrenRenderProperties(
-            smallestRenderWidth: minRenderWidth,
-            largestRenderWidth: defaultMaxRenderWidth,
-            smallestRenderHeight: minRenderHeight,
-            largestRenderHeight: defaultMaxRenderHeight,
-            maxSizeAvailable: maxSizeAvailable,
-          );
-          expect(renderProps.length, 3);
-          expect(renderProps, [
-            RenderProperties(
-              axis: Axis.horizontal,
-              size: const Size(261.5, 500.0),
-              realSize: const Size(75.0, 25.0),
-              offset: const Offset(400.0, 0.0),
-              layoutProperties: properties,
-            ),
-            RenderProperties(
-              axis: Axis.horizontal,
-              size: const Size(250.0, 250.0),
-              realSize: const Size(50.0, 0.0),
-              offset: const Offset(661.5, 125.0),
-              layoutProperties: properties,
-            ),
-            RenderProperties(
-              axis: Axis.horizontal,
-              size: const Size(400, 500),
-              realSize: const Size(375.0, 25.0),
-              offset: const Offset(0.0, 0.0),
-              isFreeSpace: true,
-              layoutProperties: properties,
-            ),
-          ]);
-        },
-      );
-
-      testWidgets(
-        'when the start is not top left, render properties should be equals to its mirrored version',
-        (tester) async {
-          Row buildWidget({
-            required bool flipMainAxis,
-            required MainAxisAlignment mainAxisAlignment,
-          }) => Row(
-            textDirection: flipMainAxis ? TextDirection.rtl : TextDirection.ltr,
-            mainAxisAlignment: flipMainAxis
-                ? mainAxisAlignment.reversed
-                : mainAxisAlignment,
-            children: flipMainAxis
-                ? childrenWidgets.reversed.toList()
-                : childrenWidgets,
-          );
-          for (final mainAxisAlignment in MainAxisAlignment.values) {
-            final originalWidgetRenderProperties = childrenRenderProperties(
-              await toFlexLayoutProperties(
-                buildWidget(
-                  flipMainAxis: false,
-                  mainAxisAlignment: mainAxisAlignment,
-                ),
-                tester: tester,
-              ),
-            );
-            final mirroredWidgetRenderProperties = childrenRenderProperties(
-              await toFlexLayoutProperties(
-                buildWidget(
-                  flipMainAxis: true,
-                  mainAxisAlignment: mainAxisAlignment,
-                ),
-                tester: tester,
-              ),
-            );
-            expect(
-              originalWidgetRenderProperties,
-              mirroredWidgetRenderProperties,
-            );
-          }
-        },
-      );
-    });
-  });
-
-  group('LayoutProperties tests', () {
-    testWidgets('deserializes RemoteDiagnosticsNode correctly', (tester) async {
-      const constraints = BoxConstraints(
-        minWidth: 432.0,
-        maxWidth: 432.0,
-        minHeight: 56.0,
-        maxHeight: 56.0,
-      );
-      const size = Size(432.0, 56.0);
-      final widget = Container(
-        width: size.width,
-        height: size.height,
-        constraints: constraints,
-        child: const Row(children: [SizedBox()]),
-      );
-      final diagnosticsNode = await widgetToLayoutExplorerRemoteDiagnosticsNode(
-        widget: widget,
-        tester: tester,
-        subtreeDepth: 2,
-      );
-      final rowDiagnosticsNode = diagnosticsNode.childrenNow.first;
-      final layoutProperties = LayoutProperties(rowDiagnosticsNode);
-
-      expect(layoutProperties.size, size);
-      expect(layoutProperties.constraints, constraints);
-      expect(layoutProperties.totalChildren, 1);
-    });
-
-    group('describeWidthConstraints and describeHeightConstraints', () {
-      testWidgets('single value', (tester) async {
-        const width = 25.0;
-        const height = 56.0;
-        const constraints = BoxConstraints.tightFor(
-          width: width,
-          height: height,
-        );
-        final widget = ConstrainedBox(
-          constraints: constraints,
-          child: const SizedBox(),
-        );
-        final constrainedBoxDiagnosticsNode =
-            await widgetToLayoutExplorerRemoteDiagnosticsNode(
-              widget: widget,
-              tester: tester,
-            );
-        final sizedBoxDiagnosticsNode =
-            constrainedBoxDiagnosticsNode.childrenNow.first;
-        final layoutProperties = LayoutProperties(sizedBoxDiagnosticsNode);
-        expect(layoutProperties.describeHeightConstraints(), 'h=$height');
-        expect(layoutProperties.describeWidthConstraints(), 'w=$width');
-      });
-
-      testWidgets('range value', (tester) async {
-        const minWidth = 25.0, maxWidth = 50.0;
-        const minHeight = 75.0, maxHeight = 100.0;
-        const constraints = BoxConstraints(
-          minWidth: minWidth,
-          maxWidth: maxWidth,
-          minHeight: minHeight,
-          maxHeight: maxHeight,
-        );
-        final widget = ConstrainedBox(
-          constraints: constraints,
-          child: const SizedBox(),
-        );
-        final constrainedBoxDiagnosticsNode =
-            await widgetToLayoutExplorerRemoteDiagnosticsNode(
-              widget: widget,
-              tester: tester,
-            );
-        final sizedBoxDiagnosticsNode =
-            constrainedBoxDiagnosticsNode.childrenNow.first;
-        final layoutProperties = LayoutProperties(sizedBoxDiagnosticsNode);
-        expect(
-          layoutProperties.describeHeightConstraints(),
-          '$minHeight<=h<=$maxHeight',
-        );
-        expect(
-          layoutProperties.describeWidthConstraints(),
-          '$minWidth<=w<=$maxWidth',
-        );
-      });
-
-      testWidgets('unconstrained width', (tester) async {
-        final widget = Row(children: [Container()]);
-        final rowDiagnosticsNode =
-            await widgetToLayoutExplorerRemoteDiagnosticsNode(
-              widget: widget,
-              tester: tester,
-            );
-        final containerDiagnosticsNode = rowDiagnosticsNode.childrenNow.first;
-        final layoutProperties = LayoutProperties(containerDiagnosticsNode);
-        expect(
-          layoutProperties.describeWidthConstraints(),
-          'width is unconstrained',
-        );
-      });
-
-      testWidgets('unconstrained height', (tester) async {
-        final widget = Column(children: [Container()]);
-        final columnDiagnosticsNode =
-            await widgetToLayoutExplorerRemoteDiagnosticsNode(
-              widget: widget,
-              tester: tester,
-            );
-        final containerDiagnosticsNode =
-            columnDiagnosticsNode.childrenNow.first;
-        final layoutProperties = LayoutProperties(containerDiagnosticsNode);
-        expect(
-          layoutProperties.describeHeightConstraints(),
-          'height is unconstrained',
-        );
-      });
-    });
-
-    testWidgets('describeWidth and describeHeight', (tester) async {
-      const width = 432.5, height = 56.0;
-      final widget = SizedBox(width: width, height: height, child: Container());
-      final sizedBoxNode = await widgetToLayoutExplorerRemoteDiagnosticsNode(
-        widget: widget,
-        tester: tester,
-      );
-      final containerNode = sizedBoxNode.childrenNow.first;
-      final layoutProperties = LayoutProperties(containerNode);
-      expect(layoutProperties.describeHeight(), 'h=$height');
-      expect(layoutProperties.describeWidth(), 'w=$width');
-    });
-  });
-
-  group('computeRenderSizes', () {
-    test(
-      'scale sizes so the largestSize maps to largestRenderSize with forceToOccupyMaxSize=false',
-      () {
-        final renderSizes = computeRenderSizes(
-          sizes: [100.0, 200.0, 300.0],
-          smallestSize: 100.0,
-          largestSize: 300.0,
-          smallestRenderSize: 200.0,
-          largestRenderSize: 600.0,
-          maxSizeAvailable: 2000,
-          useMaxSizeAvailable: false,
-        );
-        expect(renderSizes, [200.0, 400.0, 600.0]);
-        expect(sum(renderSizes), lessThan(2000));
-      },
-    );
-
-    test(
-      'scale sizes so the items fit maxSizeAvailable with forceToOccupyMaxSize=true',
-      () {
-        final renderSizes = computeRenderSizes(
-          sizes: [100.0, 200.0, 300.0],
-          smallestSize: 100.0,
-          largestSize: 300.0,
-          smallestRenderSize: 200.0,
-          largestRenderSize: 600.0,
-          maxSizeAvailable: 2000,
-        );
-        expect(renderSizes, [200.0, 666.6666666666667, 1133.3333333333335]);
-        expect(sum(renderSizes) - 2000.0, lessThan(0.01));
-      },
-    );
-
-    test(
-      'scale sizes when the items exceeds maxSizeAvailable with forceToOccupyMaxSize=true should not change any behavior',
-      () {
-        final renderSizes = computeRenderSizes(
-          sizes: [100.0, 200.0, 300.0],
-          smallestSize: 100.0,
-          largestSize: 300.0,
-          smallestRenderSize: 300.0,
-          largestRenderSize: 900.0,
-          maxSizeAvailable: 250.0,
-        );
-        expect(renderSizes, [300.0, 600.0, 900.0]);
-        expect(sum(renderSizes), greaterThan(250.0));
-      },
-    );
-  });
-}
diff --git a/packages/devtools_app/test/screens/inspector/layout_explorer/layout_explorer_serialization_delegate.dart b/packages/devtools_app/test/screens/inspector/layout_explorer/layout_explorer_serialization_delegate.dart
deleted file mode 100644
index 3f1b609..0000000
--- a/packages/devtools_app/test/screens/inspector/layout_explorer/layout_explorer_serialization_delegate.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2020 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:flutter/rendering.dart';
-import 'package:flutter/widgets.dart';
-
-/// This class is merely a duplicate of the InspectorSerializationDelegate inside the `assets/scripts/inspector_polyfill_script.dart`.
-/// This delegate is used for testing Widget Diagnostics Node so that we don't have to create manual JSON each time we want to create new test cases.
-/// TODO(adalberht): Ask Jacob on what's the better solution on code reuse between the Layout Explorer polyfillscripts and the code inside test package?
-class LayoutExplorerSerializationDelegate
-    extends InspectorSerializationDelegate {
-  LayoutExplorerSerializationDelegate({
-    String super.groupName = '',
-    super.subtreeDepth,
-    required super.service,
-  }) : super(
-         summaryTree: true,
-         addAdditionalPropertiesCallback: (node, delegate) {
-           final additionalJson = <String, Object>{};
-           final value = node.value;
-           if (value is Element) {
-             final renderObject = value.renderObject!;
-             additionalJson['renderObject'] = renderObject
-                 .toDiagnosticsNode()
-                 .toJsonMap(
-                   delegate.copyWith(subtreeDepth: 0, includeProperties: true),
-                 );
-             // Required for test.
-             // ignore: invalid_use_of_protected_member
-             final constraints = renderObject.constraints;
-
-             final constraintsProperty = <String, Object>{
-               'type': constraints.runtimeType.toString(),
-               'description': constraints.toString(),
-             };
-             if (constraints is BoxConstraints) {
-               constraintsProperty.addAll(<String, Object>{
-                 'minWidth': constraints.minWidth.toString(),
-                 'minHeight': constraints.minHeight.toString(),
-                 'maxWidth': constraints.maxWidth.toString(),
-                 'maxHeight': constraints.maxHeight.toString(),
-               });
-             }
-             additionalJson['constraints'] = constraintsProperty;
-
-             if (renderObject is RenderBox) {
-               additionalJson['size'] = <String, Object>{
-                 'width': renderObject.size.width.toString(),
-                 'height': renderObject.size.height.toString(),
-               };
-
-               final parentData = renderObject.parentData;
-               if (parentData is FlexParentData) {
-                 additionalJson['flexFactor'] = parentData.flex ?? 0;
-                 additionalJson['flexFit'] =
-                     (parentData.fit ?? FlexFit.tight).name;
-               }
-             }
-           }
-           return additionalJson;
-         },
-       );
-}
diff --git a/packages/devtools_app/test/screens/inspector/layout_explorer/layout_explorer_test_utils.dart b/packages/devtools_app/test/screens/inspector/layout_explorer/layout_explorer_test_utils.dart
deleted file mode 100644
index c2b1f44..0000000
--- a/packages/devtools_app/test/screens/inspector/layout_explorer/layout_explorer_test_utils.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2020 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/src/shared/diagnostics/diagnostics_node.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import 'layout_explorer_serialization_delegate.dart';
-
-Future<RemoteDiagnosticsNode> widgetToLayoutExplorerRemoteDiagnosticsNode({
-  required Widget widget,
-  required WidgetTester tester,
-  int subtreeDepth = 1,
-}) async {
-  await tester.pumpWidget(MaterialApp(home: Scaffold(body: widget)));
-  final element = find.byWidget(widget).evaluate().first;
-  final nodeJson = element
-      .toDiagnosticsNode(style: DiagnosticsTreeStyle.dense)
-      .toJsonMap(
-        LayoutExplorerSerializationDelegate(
-          subtreeDepth: subtreeDepth,
-          service: WidgetInspectorService.instance,
-        ),
-      );
-  return RemoteDiagnosticsNode(nodeJson, null, false, null);
-}
diff --git a/packages/devtools_app/test/screens/inspector/layout_explorer/widget_theme_test.dart b/packages/devtools_app/test/screens/inspector/layout_explorer/widget_theme_test.dart
deleted file mode 100644
index 95beb1f..0000000
--- a/packages/devtools_app/test/screens/inspector/layout_explorer/widget_theme_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/src/screens/inspector/layout_explorer/ui/widgets_theme.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-void main() {
-  group('Test WidgetTheme', () {
-    test('Correct asset from widget with a type', () {
-      const widgetName = 'AnimatedBuilder<String>';
-      final theme = WidgetTheme.fromName(widgetName);
-      expect(theme.iconAsset, 'icons/inspector/widget_icons/animated.png');
-    });
-
-    test('Has default theme for custom widget', () {
-      const widgetName = 'CustomWidget';
-      final theme = WidgetTheme.fromName(widgetName);
-      expect(theme.color, WidgetTheme.otherWidgetColor);
-    });
-  });
-}
diff --git a/packages/devtools_app/test/screens/inspector/utils/inspector_tree.dart b/packages/devtools_app/test/screens/inspector/utils/inspector_tree.dart
deleted file mode 100644
index 8896361..0000000
--- a/packages/devtools_app/test/screens/inspector/utils/inspector_tree.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2021 The Flutter Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
-
-import 'package:devtools_app/devtools_app.dart';
-import 'package:devtools_test/helpers.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/rendering.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-/// Create an `InspectorTreeControllerFlutter` from a single `RemoteDiagnosticsNode`
-InspectorTreeController inspectorTreeControllerFromNode(
-  RemoteDiagnosticsNode node,
-) {
-  final controller = InspectorTreeController()
-    ..config = InspectorTreeConfig(
-      onNodeAdded: (_, _) {},
-      onClientActiveChange: (_) {},
-    );
-
-  controller.root = InspectorTreeNode()
-    ..appendChild(InspectorTreeNode()..diagnostic = node);
-
-  return controller;
-}
-
-/// Replicates the functionality of `getRootWidgetSummaryTreeWithPreviews` from
-/// inspector_polyfill_script.dart
-Future<RemoteDiagnosticsNode> widgetToInspectorTreeDiagnosticsNode({
-  required Widget widget,
-  required WidgetTester tester,
-}) async {
-  await tester.pumpWidget(wrap(widget));
-  final element = find.byWidget(widget).evaluate().first;
-  final nodeJson = element
-      .toDiagnosticsNode(style: DiagnosticsTreeStyle.dense)
-      .toJsonMap(
-        InspectorSerializationDelegate(
-          service: WidgetInspectorService.instance,
-          subtreeDepth: 1000000,
-          summaryTree: true,
-          addAdditionalPropertiesCallback: (node, delegate) {
-            final additionalJson = <String, Object>{};
-
-            final value = node.value;
-            if (value is Element) {
-              final renderObject = value.renderObject;
-              if (renderObject is RenderParagraph) {
-                additionalJson['textPreview'] = renderObject.text.toPlainText();
-              }
-            }
-
-            return additionalJson;
-          },
-        ),
-      );
-
-  return RemoteDiagnosticsNode(nodeJson, null, false, null);
-}
diff --git a/packages/devtools_app/test/screens/inspector_v2/inspector_error_navigator_test.dart b/packages/devtools_app/test/screens/inspector_v2/inspector_error_navigator_test.dart
index 6db56eb..0d339af 100644
--- a/packages/devtools_app/test/screens/inspector_v2/inspector_error_navigator_test.dart
+++ b/packages/devtools_app/test/screens/inspector_v2/inspector_error_navigator_test.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 
 import 'package:devtools_app/devtools_app.dart';
+
 import 'package:devtools_app/src/shared/feature_flags.dart';
 import 'package:devtools_app_shared/ui.dart';
 import 'package:devtools_app_shared/utils.dart';
diff --git a/packages/devtools_app/test/screens/inspector_v2/inspector_integration_test.dart b/packages/devtools_app/test/screens/inspector_v2/inspector_integration_test.dart
index c9f902f..2e5a7fa 100644
--- a/packages/devtools_app/test/screens/inspector_v2/inspector_integration_test.dart
+++ b/packages/devtools_app/test/screens/inspector_v2/inspector_integration_test.dart
@@ -8,13 +8,7 @@
 import 'dart:io';
 
 import 'package:collection/collection.dart';
-import 'package:devtools_app/devtools_app.dart'
-    hide InspectorScreenBodyState, InspectorScreenBody, InspectorRowContent;
-import 'package:devtools_app/src/screens/inspector/inspector_screen_body.dart'
-    as legacy;
-import 'package:devtools_app/src/screens/inspector_shared/inspector_controls.dart';
-import 'package:devtools_app/src/screens/inspector_v2/inspector_screen_body.dart';
-import 'package:devtools_app/src/screens/inspector_v2/inspector_tree_controller.dart';
+import 'package:devtools_app/devtools_app.dart';
 import 'package:devtools_app/src/screens/inspector_v2/layout_explorer/ui/utils.dart';
 import 'package:devtools_app/src/screens/inspector_v2/widget_properties/properties_view.dart';
 import 'package:devtools_app_shared/ui.dart';
@@ -63,15 +57,11 @@
 
   setUp(() async {
     await env.setupEnvironment();
-    // Enable the V2 inspector:
-    preferences.inspector.setLegacyInspectorEnabled(false);
     setGlobal(BannerMessagesController, BannerMessagesController());
   });
 
   tearDown(() async {
     await env.tearDownEnvironment(force: true);
-    // Re-set changes to preferences:
-    preferences.inspector.setLegacyInspectorEnabled(true);
   });
 
   tearDownAll(() {
@@ -369,65 +359,6 @@
     );
   });
 
-  testWidgetsWithWindowSize('can revert to legacy inspector', windowSize, (
-    WidgetTester tester,
-  ) async {
-    await _loadInspectorUI(tester);
-
-    // Select the CustomCenter widget (row index #4)
-    await tester.tap(find.richText('CustomCenter'));
-    await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-    // Disable Inspector V2:
-    await toggleLegacyInspector(tester);
-    await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-    // Verify the legacy inspector is visible:
-    await expectLater(
-      find.byType(legacy.InspectorScreenBody),
-      matchesDevToolsGolden(
-        '../../test_infra/goldens/integration_inspector_v2_revert_to_legacy.png',
-      ),
-    );
-  });
-
-  // Test to verify https://github.com/flutter/devtools/issues/8487 is fixed.
-  testWidgetsWithWindowSize(
-    'revert to legacy inspector, hot-restart, and back to new inspector',
-    windowSize,
-    (WidgetTester tester) async {
-      await _loadInspectorUI(tester);
-
-      // Disable Inspector V2.
-      await toggleLegacyInspector(tester);
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-      // Verify the legacy inspector is visible.
-      expect(find.richTextContaining('Widget Details Tree'), findsOneWidget);
-
-      // Trigger a hot restart.
-      await env.flutter!.hotRestart();
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-      // Enable Inspector V2.
-      await toggleLegacyInspector(tester);
-      await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-      // Verify the legacy inspector is not visible.
-      expect(find.richTextContaining('Widget Details Tree'), findsNothing);
-
-      // Wait for the widget tree to load.
-      final centerWidgetFinder = find.richText('Center');
-      final centerWidgetFinderWithRetries = await retryUntilFound(
-        centerWidgetFinder,
-        tester: tester,
-        retries: 10,
-      );
-      expect(centerWidgetFinderWithRetries, findsOneWidget);
-    },
-    skip: true, // https://github.com/flutter/devtools/issues/8490
-  );
-
   testWidgetsWithWindowSize(
     'tree nodes contain only essential information',
     windowSize,
@@ -688,33 +619,6 @@
   return expandCollapseButtonFinder;
 }
 
-Future<void> toggleLegacyInspector(WidgetTester tester) async {
-  // Open settings dialog.
-  final inspectorSettingsDialogButton = find.descendant(
-    of: find.byType(InspectorServiceExtensionButtonGroup),
-    matching: find.byType(SettingsOutlinedButton),
-  );
-  await tester.tap(inspectorSettingsDialogButton);
-  await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-  // Toggle the "legacy Inspector" checkbox.
-  final settingsRow = find.ancestor(
-    of: find.richTextContaining('Use legacy inspector'),
-    matching: find.byType(Row),
-  );
-  final inspectorCheckbox = find.descendant(
-    of: settingsRow,
-    matching: find.byType(NotifierCheckbox),
-  );
-  await tester.tap(inspectorCheckbox);
-  await tester.pumpAndSettle(inspectorChangeSettleTime);
-
-  // Close the settings dialog.
-  final closeButton = find.byType(DialogCloseButton);
-  await tester.tap(closeButton);
-  await tester.pumpAndSettle(inspectorChangeSettleTime);
-}
-
 void verifyPropertyIsVisible({
   required String name,
   required String value,
diff --git a/packages/devtools_app/test/screens/inspector_v2/inspector_screen_test.dart b/packages/devtools_app/test/screens/inspector_v2/inspector_screen_test.dart
index 813cc1e..2886318 100644
--- a/packages/devtools_app/test/screens/inspector_v2/inspector_screen_test.dart
+++ b/packages/devtools_app/test/screens/inspector_v2/inspector_screen_test.dart
@@ -7,19 +7,11 @@
 
 import 'dart:convert';
 
-import 'package:devtools_app/devtools_app.dart'
-    hide
-        InspectorController,
-        InspectorTreeController,
-        InspectorScreenBody,
-        ErrorNavigator,
-        InspectorTreeNode;
-import 'package:devtools_app/src/screens/inspector_shared/inspector_settings_dialog.dart';
-import 'package:devtools_app/src/screens/inspector_v2/inspector_screen_body.dart';
+import 'package:devtools_app/devtools_app.dart';
+import 'package:devtools_app/src/screens/inspector_v2/inspector_settings_dialog.dart';
 import 'package:devtools_app/src/screens/inspector_v2/layout_explorer/flex/flex.dart';
 import 'package:devtools_app/src/screens/inspector_v2/widget_details.dart';
 import 'package:devtools_app/src/service/service_extensions.dart' as extensions;
-import 'package:devtools_app/src/shared/console/eval/inspector_tree_v2.dart';
 import 'package:devtools_app/src/shared/feature_flags.dart';
 import 'package:devtools_app/src/shared/ui/tab.dart';
 import 'package:devtools_app_shared/ui.dart';
@@ -311,7 +303,7 @@
       'should render StoryOfYourFlexWidget',
       windowSize,
       (WidgetTester tester) async {
-        final controller = TestInspectorV2Controller()
+        final controller = TestInspectorController()
           ..setSelectedNode(treeNode)
           ..setSelectedDiagnostic(diagnostic);
         await tester.pumpWidget(
@@ -332,7 +324,7 @@
       'should listen to controller selection event',
       windowSize,
       (WidgetTester tester) async {
-        final controller = TestInspectorV2Controller();
+        final controller = TestInspectorController();
         await tester.pumpWidget(
           MaterialApp(
             home: Scaffold(body: WidgetDetails(controller: controller)),
diff --git a/packages/devtools_app/test/screens/inspector_v2/inspector_tree_test.dart b/packages/devtools_app/test/screens/inspector_v2/inspector_tree_test.dart
index 5a7c896..feda195 100644
--- a/packages/devtools_app/test/screens/inspector_v2/inspector_tree_test.dart
+++ b/packages/devtools_app/test/screens/inspector_v2/inspector_tree_test.dart
@@ -2,16 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
-import 'package:devtools_app/devtools_app.dart'
-    hide
-        InspectorController,
-        InspectorTreeController,
-        InspectorTree,
-        InspectorTreeConfig,
-        InspectorTreeNode;
-import 'package:devtools_app/src/screens/inspector_v2/inspector_controller.dart';
-import 'package:devtools_app/src/screens/inspector_v2/inspector_tree_controller.dart';
-import 'package:devtools_app/src/shared/console/eval/inspector_tree_v2.dart';
+import 'package:devtools_app/devtools_app.dart';
+
 import 'package:devtools_app_shared/ui.dart';
 import 'package:devtools_app_shared/utils.dart';
 import 'package:devtools_test/devtools_test.dart';
diff --git a/packages/devtools_app/test/screens/inspector_v2/layout_explorer/flex/flex_test.dart b/packages/devtools_app/test/screens/inspector_v2/layout_explorer/flex/flex_test.dart
index 5f4ea4a..9c64239 100644
--- a/packages/devtools_app/test/screens/inspector_v2/layout_explorer/flex/flex_test.dart
+++ b/packages/devtools_app/test/screens/inspector_v2/layout_explorer/flex/flex_test.dart
@@ -260,7 +260,7 @@
       null,
     );
     final treeNode = InspectorTreeNode()..diagnostic = diagnostic;
-    final controller = TestInspectorV2Controller()..setSelectedNode(treeNode);
+    final controller = TestInspectorController()..setSelectedNode(treeNode);
     final widget = wrap(FlexLayoutExplorerWidget(controller));
     await pump(tester, widget);
     await tester.pumpAndSettle();
@@ -281,7 +281,7 @@
       null,
     );
     final treeNode = InspectorTreeNode()..diagnostic = diagnostic;
-    final controller = TestInspectorV2Controller()..setSelectedNode(treeNode);
+    final controller = TestInspectorController()..setSelectedNode(treeNode);
     final widget = wrap(FlexLayoutExplorerWidget(controller));
     await pump(tester, widget);
     await expectLater(
diff --git a/packages/devtools_app/test/screens/inspector_v2/utils/inspector_tree.dart b/packages/devtools_app/test/screens/inspector_v2/utils/inspector_tree.dart
index d2aac27..8896361 100644
--- a/packages/devtools_app/test/screens/inspector_v2/utils/inspector_tree.dart
+++ b/packages/devtools_app/test/screens/inspector_v2/utils/inspector_tree.dart
@@ -2,10 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
-import 'package:devtools_app/devtools_app.dart'
-    hide InspectorTreeController, InspectorTreeConfig, InspectorTreeNode;
-import 'package:devtools_app/src/screens/inspector_v2/inspector_tree_controller.dart';
-import 'package:devtools_app/src/shared/console/eval/inspector_tree_v2.dart';
+import 'package:devtools_app/devtools_app.dart';
 import 'package:devtools_test/helpers.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
diff --git a/packages/devtools_app/test/shared/managers/error_badge_manager_test.dart b/packages/devtools_app/test/shared/managers/error_badge_manager_test.dart
index 69b74f5..13ea519 100644
--- a/packages/devtools_app/test/shared/managers/error_badge_manager_test.dart
+++ b/packages/devtools_app/test/shared/managers/error_badge_manager_test.dart
@@ -4,7 +4,7 @@
 
 import 'package:devtools_app/src/screens/app_size/app_size_screen.dart';
 import 'package:devtools_app/src/screens/debugger/debugger_screen.dart';
-import 'package:devtools_app/src/screens/inspector_shared/inspector_screen.dart';
+import 'package:devtools_app/src/screens/inspector_v2/inspector_screen.dart';
 import 'package:devtools_app/src/screens/logging/logging_screen.dart';
 import 'package:devtools_app/src/screens/memory/framework/memory_screen.dart';
 import 'package:devtools_app/src/screens/network/network_screen.dart';
diff --git a/packages/devtools_app/test/test_infra/goldens/integration_inspector_v2_implementation_widgets_collapsed.png b/packages/devtools_app/test/test_infra/goldens/integration_inspector_v2_implementation_widgets_collapsed.png
index e148d46..d719b72 100644
--- a/packages/devtools_app/test/test_infra/goldens/integration_inspector_v2_implementation_widgets_collapsed.png
+++ b/packages/devtools_app/test/test_infra/goldens/integration_inspector_v2_implementation_widgets_collapsed.png
Binary files differ
diff --git a/packages/devtools_app/test/test_infra/goldens/memory/load_offline_data_profile_tab.png b/packages/devtools_app/test/test_infra/goldens/memory/load_offline_data_profile_tab.png
index 3faf47d..0693188 100644
--- a/packages/devtools_app/test/test_infra/goldens/memory/load_offline_data_profile_tab.png
+++ b/packages/devtools_app/test/test_infra/goldens/memory/load_offline_data_profile_tab.png
Binary files differ
diff --git a/packages/devtools_test/lib/src/mocks/mocks.dart b/packages/devtools_test/lib/src/mocks/mocks.dart
index fee470e..d4fd888 100644
--- a/packages/devtools_test/lib/src/mocks/mocks.dart
+++ b/packages/devtools_test/lib/src/mocks/mocks.dart
@@ -7,12 +7,6 @@
 import 'dart:io';
 
 import 'package:devtools_app/devtools_app.dart';
-// ignore: implementation_imports, required to separate V2 inspector imports.
-import 'package:devtools_app/src/screens/inspector_v2/inspector_controller.dart'
-    as inspector_v2;
-// ignore: implementation_imports, required to separate V2 inspector imports.
-import 'package:devtools_app/src/shared/console/eval/inspector_tree_v2.dart'
-    as inspector_v2;
 import 'package:devtools_app_shared/service.dart';
 import 'package:devtools_shared/devtools_shared.dart';
 import 'package:flutter/foundation.dart';
@@ -78,38 +72,19 @@
   final _selectedNode = ValueNotifier<InspectorTreeNode?>(null);
 
   @override
-  void setSelectedNode(InspectorTreeNode? newSelection) {
-    _selectedNode.value = newSelection;
-  }
-
-  @override
-  InspectorService get inspectorService => service;
-}
-
-class TestInspectorV2Controller extends Fake
-    implements inspector_v2.InspectorController {
-  InspectorService service = FakeInspectorService();
-
-  @override
-  ValueListenable<inspector_v2.InspectorTreeNode?> get selectedNode =>
-      _selectedNode;
-  final _selectedNode = ValueNotifier<inspector_v2.InspectorTreeNode?>(null);
-
-  @override
   RemoteDiagnosticsNode? get selectedDiagnostic => _selectedDiagnostic;
   RemoteDiagnosticsNode? _selectedDiagnostic;
 
   @override
-  ValueListenable<inspector_v2.WidgetTreeNodeProperties>
-  get selectedNodeProperties =>
-      ValueNotifier<inspector_v2.WidgetTreeNodeProperties>((
+  ValueListenable<WidgetTreeNodeProperties> get selectedNodeProperties =>
+      ValueNotifier<WidgetTreeNodeProperties>((
         widgetProperties: [],
         renderProperties: [],
         layoutProperties: null,
       ));
 
   @override
-  void setSelectedNode(inspector_v2.InspectorTreeNode? newSelection) {
+  void setSelectedNode(InspectorTreeNode? newSelection) {
     _selectedNode.value = newSelection;
   }