Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

import 'package:devtools_app_shared/service.dart';
import 'package:devtools_app_shared/utils.dart';
import 'package:flutter/foundation.dart';

import '../../shared/framework/screen.dart';
import '../../shared/framework/screen_controllers.dart';
import '../../shared/globals.dart';
import '../../shared/globals.dart' as globals;

/// The [DevToolsScreenController] for the `DTDTools` screen.
///
Expand All @@ -17,29 +18,45 @@ class DTDToolsController extends DevToolsScreenController
@override
final screenId = ScreenMetaData.dtdTools.id;

bool get useGlobalDtd => _useGlobalDtd && kDebugMode;
bool _useGlobalDtd = false;

/// The [DTDManager] that manages the DTD connection for this screen.
///
/// This instance of [DTDManager] is intentionally separate from the global
/// [DTDManager] so that we can connect and disconnect from DTD instances
/// to inspect them without affecting other screens.
final localDtdManager = DTDManager();
/// By default, this instance of [DTDManager] is intentionally separate from
/// the global [DTDManager] so that we can connect and disconnect from DTD
/// instances to inspect them without affecting other screens.
///
/// However, in debug mode, we can optionally use the global [DTDManager]
/// (if specifically requested) to set the DTD instance that the entire
/// DevTools is connected to.
DTDManager get activeDtdManager =>
useGlobalDtd ? globals.dtdManager : _localDtdManager;
DTDManager get localDtdManager => _localDtdManager;

final _localDtdManager = DTDManager();

@override
Future<void> init() async {
if (dtdManager.hasConnection) {
await localDtdManager.connect(dtdManager.uri!);
if (globals.dtdManager.hasConnection) {
await activeDtdManager.connect(globals.dtdManager.uri!);
}
addAutoDisposeListener(dtdManager.connection, () async {
if (dtdManager.hasConnection) {
await localDtdManager.connect(dtdManager.uri!);
addAutoDisposeListener(globals.dtdManager.connection, () async {
if (globals.dtdManager.hasConnection && !_useGlobalDtd) {
await activeDtdManager.connect(globals.dtdManager.uri!);
}
});
}

Future<void> connectDtd(Uri uri, {bool connectToGlobalDtd = false}) async {
_useGlobalDtd = connectToGlobalDtd;
await activeDtdManager.connect(uri);
}

@override
Future<void> dispose() async {
await localDtdManager.disconnect();
await localDtdManager.dispose();
await activeDtdManager.disconnect();
await activeDtdManager.dispose();
super.dispose();
}
}
85 changes: 72 additions & 13 deletions packages/devtools_app/lib/src/screens/dtd/dtd_tools_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

import 'dart:async';

import 'package:devtools_app_shared/service.dart';
import 'package:devtools_app_shared/ui.dart';
import 'package:dtd/dtd.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import '../../shared/development_helpers.dart';
import '../../shared/framework/screen.dart';
import '../../shared/globals.dart';
import '../../shared/ui/common_widgets.dart';
import 'dtd_tools_controller.dart';
import 'events.dart';
import 'services.dart';
Expand Down Expand Up @@ -39,15 +40,22 @@ class DTDToolsScreenBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = screenControllers.lookup<DTDToolsController>();
return ValueListenableBuilder(
valueListenable: controller.localDtdManager.connection,
builder: (context, connection, _) => connection != null
? DtdConnectedView(
dtd: connection,
dtdUri: controller.localDtdManager.uri!.toString(),
onDisconnect: controller.localDtdManager.disconnect,
)
: DtdNotConnectedView(localDtdManager: controller.localDtdManager),
return MultiValueListenableBuilder(
listenables: [
controller.localDtdManager.connection,
dtdManager.connection,
],
builder: (context, values, _) {
final activeDtdManager = controller.activeDtdManager;
final connection = activeDtdManager.connection.value;
return connection != null
? DtdConnectedView(
dtd: connection,
dtdUri: activeDtdManager.uri!.toString(),
onDisconnect: activeDtdManager.disconnect,
)
: DtdNotConnectedView(connectDtd: controller.connectDtd);
},
);
}
}
Expand Down Expand Up @@ -111,6 +119,7 @@ class _DtdConnectedViewState extends State<DtdConnectedView> {

@override
Widget build(BuildContext context) {
final isGlobalDtd = widget.dtd == dtdManager.connection.value;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
Expand All @@ -122,6 +131,14 @@ class _DtdConnectedViewState extends State<DtdConnectedView> {
children: [
Text('DTD connection:', style: Theme.of(context).boldTextStyle),
const SizedBox(width: denseSpacing),
DevToolsTooltip(
message:
'This DTD URI is being used for ${isGlobalDtd ? 'all of DevTools.' : 'this screen only.'}',
child: RoundedLabel(
labelText: isGlobalDtd ? 'Global' : 'Local',
),
),
const SizedBox(width: defaultSpacing),
Text(widget.dtdUri),
const SizedBox(width: defaultSpacing),
DevToolsButton(
Expand Down Expand Up @@ -156,9 +173,9 @@ class _DtdConnectedViewState extends State<DtdConnectedView> {
/// Displays a text field for entering a DTD URI to connect the DTD Tools screen
/// to.
class DtdNotConnectedView extends StatefulWidget {
const DtdNotConnectedView({super.key, required this.localDtdManager});
const DtdNotConnectedView({super.key, required this.connectDtd});

final DTDManager localDtdManager;
final Future<void> Function(Uri, {bool connectToGlobalDtd}) connectDtd;

@override
State<DtdNotConnectedView> createState() => _DtdNotConnectedViewState();
Expand All @@ -167,6 +184,10 @@ class DtdNotConnectedView extends StatefulWidget {
class _DtdNotConnectedViewState extends State<DtdNotConnectedView> {
late final TextEditingController textEditingController;

bool _connectToGlobalDtd = false;

String? _connectionError;

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -198,6 +219,22 @@ class _DtdNotConnectedViewState extends State<DtdNotConnectedView> {
onSubmitted: (_) => _connect(),
),
),
if (kDebugMode) ...[
const SizedBox(width: defaultSpacing),
DevToolsTooltip(
message: 'Connect all DevTools screens to this DTD URI.',
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: _connectToGlobalDtd,
onChanged: _setConnectToGlobalDtd,
),
const Text('Connect DevTools'),
],
),
),
],
const SizedBox(width: defaultSpacing),
DevToolsButton(
label: 'Connect',
Expand All @@ -206,11 +243,33 @@ class _DtdNotConnectedViewState extends State<DtdNotConnectedView> {
),
],
),
if (_connectionError != null) ...[
const SizedBox(height: denseSpacing),
Text(_connectionError!, style: Theme.of(context).errorTextStyle),
],
],
);
}

void _setConnectToGlobalDtd(bool? shouldConnect) {
setState(() {
_connectToGlobalDtd = kDebugMode && (shouldConnect ?? false);
});
}

Future<void> _connect() async {
await widget.localDtdManager.connect(Uri.parse(textEditingController.text));
setState(() {
_connectionError = null;
});
try {
await widget.connectDtd(
Uri.parse(textEditingController.text),
connectToGlobalDtd: _connectToGlobalDtd,
);
} catch (error) {
setState(() {
_connectionError = error.toString();
});
}
}
}
Loading