diff --git a/packages/.vscode/launch.json b/packages/.vscode/launch.json index 6c6edb2281c8..f524f89cd2a7 100644 --- a/packages/.vscode/launch.json +++ b/packages/.vscode/launch.json @@ -79,19 +79,11 @@ "program": "devtools_app/test/test_infra/fixtures/memory_app/lib/main.dart", }, { - "name": "VS Code Sidebar Environment", + "name": "standalone_ui/vs_code", "request": "launch", "type": "dart", - "program": "devtools_app/lib/main.dart", - "args": [ - "--dart-define=enable_experiments=true", - // web-launch-url only works with an absolute URL so we must set hostname/port - // to match. However, this is convenient for using `dart.customDevToolsUri` for - // testing inside VS Code anyway. - "--web-hostname=localhost", - "--web-port=8765", - "--web-launch-url=http://localhost:8765/vsCodeFlutterPanelMockEditor", - ], + "program": "devtools_app/test/test_infra/scenes/standalone_ui/vs_code.stager_app.g.dart", + "deviceId": "chrome", }, { "name": "attach", diff --git a/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart b/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart index 9dec5f00233f..7bc7d62e7373 100644 --- a/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart +++ b/packages/devtools_app/lib/src/standalone_ui/standalone_screen.dart @@ -6,7 +6,6 @@ import 'package:flutter/material.dart'; import 'api/impl/dart_tooling_api.dart'; import 'vs_code/flutter_panel.dart'; -import 'vs_code/mock_environment/flutter_panel_mock_editor.dart'; /// "Screens" that are intended for standalone use only, likely for embedding /// directly in an IDE. @@ -15,8 +14,7 @@ import 'vs_code/mock_environment/flutter_panel_mock_editor.dart'; /// meaning that this screen will not be part of DevTools' normal navigation. /// The only way to access a standalone screen is directly from the url. enum StandaloneScreenType { - vsCodeFlutterPanel, - vsCodeFlutterPanelMockEditor; + vsCodeFlutterPanel; static StandaloneScreenType? parse(String? id) { if (id == null) return null; @@ -31,8 +29,6 @@ enum StandaloneScreenType { return switch (this) { StandaloneScreenType.vsCodeFlutterPanel => VsCodeFlutterPanel(DartToolingApiImpl.postMessage()), - StandaloneScreenType.vsCodeFlutterPanelMockEditor => - const VsCodeFlutterPanelMockEditor(), }; } } diff --git a/packages/devtools_app/test/test_infra/scenes/standalone_ui/vs_code.dart b/packages/devtools_app/test/test_infra/scenes/standalone_ui/vs_code.dart new file mode 100644 index 000000000000..db89c034844f --- /dev/null +++ b/packages/devtools_app/test/test_infra/scenes/standalone_ui/vs_code.dart @@ -0,0 +1,40 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +import 'package:devtools_app/devtools_app.dart'; +import 'package:devtools_app/src/shared/feature_flags.dart'; +import 'package:devtools_app/src/standalone_ui/vs_code/flutter_panel.dart'; +import 'package:flutter/material.dart'; +import 'package:stager/stager.dart'; + +import '../../test_data/dart_tooling_api/mock_api.dart'; +import 'vs_code_mock_editor.dart'; + +final _api = MockDartToolingApi(); + +/// To run, use the "standalone_ui/vs_code" launch configuration with the +/// `devtools/packages/` folder open in VS Code, or run: +/// +/// flutter run -t test/test_infra/scenes/standalone_ui/vs_code.stager_app.g.dart --dart-define=enable_experiments=true -d chrome +class VsCodeScene extends Scene { + late PerformanceController controller; + + @override + Widget build(BuildContext context) { + return VsCodeFlutterPanelMockEditor( + api: _api, + child: VsCodeFlutterPanel(_api), + ); + } + + @override + String get title => '$VsCodeScene'; + + @override + Future setUp() async { + FeatureFlags.vsCodeSidebarTooling = true; + + setGlobal(IdeTheme, IdeTheme()); + } +} diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/mock_environment/flutter_panel_mock_editor.dart b/packages/devtools_app/test/test_infra/scenes/standalone_ui/vs_code_mock_editor.dart similarity index 63% rename from packages/devtools_app/lib/src/standalone_ui/vs_code/mock_environment/flutter_panel_mock_editor.dart rename to packages/devtools_app/test/test_infra/scenes/standalone_ui/vs_code_mock_editor.dart index 277961edcec1..02f327974b9c 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/mock_environment/flutter_panel_mock_editor.dart +++ b/packages/devtools_app/test/test_infra/scenes/standalone_ui/vs_code_mock_editor.dart @@ -5,12 +5,11 @@ import 'dart:collection'; import 'dart:convert'; +import 'package:devtools_app/src/shared/split.dart'; +import 'package:devtools_app/src/shared/theme.dart'; import 'package:flutter/material.dart'; -import '../../../shared/split.dart'; -import '../../../shared/theme.dart'; -import '../flutter_panel.dart'; -import 'dart_tooling_mock_api.dart'; +import '../../test_data/dart_tooling_api/mock_api.dart'; /// A simple UI that acts as a stand-in host IDE to simplify the development /// workflow when working on embedded tooling. @@ -18,7 +17,16 @@ import 'dart_tooling_mock_api.dart'; /// This UI interacts with [MockDartToolingApi] to allow triggering events that /// would normally be fired by the IDE and also shows a log of recent requests. class VsCodeFlutterPanelMockEditor extends StatefulWidget { - const VsCodeFlutterPanelMockEditor({super.key}); + const VsCodeFlutterPanelMockEditor({ + super.key, + required this.api, + this.child, + }); + + /// The mock API to interact with. + final MockDartToolingApi api; + + final Widget? child; @override State createState() => @@ -27,8 +35,7 @@ class VsCodeFlutterPanelMockEditor extends StatefulWidget { class _VsCodeFlutterPanelMockEditorState extends State { - /// The mock API to interact with. - final api = MockDartToolingApi(); + MockDartToolingApi get api => widget.api; /// The number of communication messages to keep in the log. static const maxLogEvents = 20; @@ -61,10 +68,20 @@ class _VsCodeFlutterPanelMockEditorState @override Widget build(BuildContext context) { + final editorTheme = VsCodeTheme.of(context); return Split( axis: Axis.horizontal, - initialFractions: const [0.2, 0.8], + initialFractions: const [0.25, 0.75], minSizes: const [200, 200], + splitters: [ + PreferredSize( + preferredSize: const Size.fromWidth(1), + child: SizedBox( + width: 1, + child: ColoredBox(color: editorTheme.editorSidebarSplitterColor), + ), + ), + ], children: [ Row( children: [ @@ -74,20 +91,35 @@ class _VsCodeFlutterPanelMockEditorState alignment: Alignment.topCenter, padding: const EdgeInsets.only(top: 60), constraints: const BoxConstraints.expand(width: 48), - color: const Color(0xFF333333), + color: editorTheme.activityBarBackgroundColor, child: Image.memory(sidebarImageBytes), ), ), - Expanded(child: VsCodeFlutterPanel(api)), + Expanded( + child: Container( + color: editorTheme.sidebarBackgroundColor, + child: widget.child ?? const Placeholder(), + ), + ), ], ), Split( axis: Axis.vertical, initialFractions: const [0.5, 0.5], minSizes: const [200, 200], + splitters: [ + PreferredSize( + preferredSize: const Size.fromHeight(1), + child: SizedBox( + height: 1, + child: + ColoredBox(color: editorTheme.editorTerminalSplitterColor), + ), + ), + ], children: [ Container( - color: const Color(0xFF282828), + color: editorTheme.editorBackgroundColor, padding: const EdgeInsets.all(10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -117,7 +149,7 @@ class _VsCodeFlutterPanelMockEditorState ), ), Container( - color: const Color(0xFF222222), + color: editorTheme.editorBackgroundColor, padding: const EdgeInsets.all(10), child: StreamBuilder( stream: logUpdated, @@ -141,3 +173,41 @@ class _VsCodeFlutterPanelMockEditorState ); } } + +/// A basic theme that matches the default colours of VS Code dart/light themes +/// so the mock environment can be displayed in either. +class VsCodeTheme { + const VsCodeTheme._({ + required this.activityBarBackgroundColor, + required this.editorBackgroundColor, + required this.editorSidebarSplitterColor, + required this.editorTerminalSplitterColor, + required this.sidebarBackgroundColor, + }); + + static VsCodeTheme of(BuildContext context) { + // TODO(dantup): Figure out why Theme.of(context).isDarkTheme doesn't + // match what's in the stager sidebar. + return Theme.of(context).isDarkTheme + ? const VsCodeTheme._( + activityBarBackgroundColor: Color(0xFF333333), + editorBackgroundColor: Color(0xFF1E1E1E), + editorSidebarSplitterColor: Color(0xFF252526), + editorTerminalSplitterColor: Color(0xFF414141), + sidebarBackgroundColor: Color(0xFF252526), + ) + : const VsCodeTheme._( + activityBarBackgroundColor: Color(0xFF2C2C2C), + editorBackgroundColor: Color(0xFFFFFFFF), + editorSidebarSplitterColor: Color(0xFFF3F3F3), + editorTerminalSplitterColor: Color(0xFFC4C4C4), + sidebarBackgroundColor: Color(0xFFF3F3F3), + ); + } + + final Color activityBarBackgroundColor; + final Color editorBackgroundColor; + final Color editorSidebarSplitterColor; + final Color editorTerminalSplitterColor; + final Color sidebarBackgroundColor; +} diff --git a/packages/devtools_app/lib/src/standalone_ui/vs_code/mock_environment/dart_tooling_mock_api.dart b/packages/devtools_app/test/test_infra/test_data/dart_tooling_api/mock_api.dart similarity index 93% rename from packages/devtools_app/lib/src/standalone_ui/vs_code/mock_environment/dart_tooling_mock_api.dart rename to packages/devtools_app/test/test_infra/test_data/dart_tooling_api/mock_api.dart index 63f8d1c9df08..3acf15b95098 100644 --- a/packages/devtools_app/lib/src/standalone_ui/vs_code/mock_environment/dart_tooling_mock_api.dart +++ b/packages/devtools_app/test/test_infra/test_data/dart_tooling_api/mock_api.dart @@ -4,15 +4,14 @@ import 'dart:async'; +import 'package:devtools_app/src/standalone_ui/api/impl/dart_tooling_api.dart'; +import 'package:devtools_app/src/standalone_ui/api/impl/vs_code_api.dart'; +import 'package:devtools_app/src/standalone_ui/api/vs_code_api.dart'; import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc_2; import 'package:stream_channel/stream_channel.dart'; -import '../../api/impl/dart_tooling_api.dart'; -import '../../api/impl/vs_code_api.dart'; -import '../../api/vs_code_api.dart'; - -/// A [DartToolingApi] that acts as a stand-in host IDE to simplify the development -/// workflow when working on embedded tooling. +/// A [DartToolingApi] that acts as a stand-in host IDE to simplify the +/// development workflow when working on embedded tooling. /// /// This API will handle requests with canned responses and can generate /// events in a similar way to the IDE would. It is used by @@ -121,6 +120,8 @@ class MockDartToolingApi extends DartToolingApiImpl { switch (command) { case 'flutter.createProject': return null; + case 'flutter.doctor': + return null; default: throw 'Unknown command $command'; }