Skip to content

Add initial support for non-query param navigation state #4837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 7, 2022
Merged
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
53 changes: 33 additions & 20 deletions packages/devtools_app/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {

late ReleaseNotesController releaseNotesController;

late final routerDelegate = DevToolsRouterDelegate(_getPage);

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -148,13 +150,19 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
}

/// Gets the page for a given page/path and args.
Page _getPage(BuildContext context, String? page, Map<String, String?> args) {
Page _getPage(
BuildContext context,
String? page,
Map<String, String?> args,
DevToolsNavigationState? state,
) {
// Provide the appropriate page route.
if (pages.containsKey(page)) {
Widget widget = pages[page!]!(
context,
page,
args,
state,
);
assert(
() {
Expand All @@ -163,6 +171,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
context,
page,
args,
state,
),
);
return true;
Expand All @@ -185,6 +194,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
BuildContext context,
String? page,
Map<String, String?> params,
DevToolsNavigationState? state,
) {
final vmServiceUri = params['uri'];

Expand Down Expand Up @@ -262,7 +272,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
homePageId: _buildTabbedPage,
for (final screen in widget.screens)
screen.screen.screenId: _buildTabbedPage,
snapshotPageId: (_, __, args) {
snapshotPageId: (_, __, args, ___) {
final snapshotArgs = SnapshotArguments.fromArgs(args);
return DevToolsScaffold.withChild(
key: UniqueKey(),
Expand All @@ -273,7 +283,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
),
);
},
appSizePageId: (_, __, ___) {
appSizePageId: (_, __, ___, ____) {
return DevToolsScaffold.withChild(
key: const Key('appsize'),
ideTheme: ideTheme,
Expand Down Expand Up @@ -303,7 +313,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
.where(
(s) => s.providesController && (offline ? s.supportsOffline : true),
)
.map((s) => s.controllerProvider)
.map((s) => s.controllerProvider(routerDelegate))
.toList();

return MultiProvider(
Expand Down Expand Up @@ -339,7 +349,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
),
);
},
routerDelegate: DevToolsRouterDelegate(_getPage),
routerDelegate: routerDelegate,
routeInformationParser: DevToolsRouteInformationParser(),
// Disable default scrollbar behavior on web to fix duplicate scrollbars
// bug, see https://github.com/flutter/flutter/issues/90697:
Expand Down Expand Up @@ -372,7 +382,7 @@ class DevToolsScreen<C> {
///
/// If [createController] and [controller] are both null, [screen] will be
/// responsible for creating and maintaining its own controller.
final C Function()? createController;
final C Function(DevToolsRouterDelegate)? createController;

/// A provided controller for this screen, if non-null.
///
Expand All @@ -393,7 +403,7 @@ class DevToolsScreen<C> {
/// Defaults to false.
final bool supportsOffline;

Provider<C> get controllerProvider {
Provider<C> controllerProvider(DevToolsRouterDelegate routerDelegate) {
assert(
(createController != null && controller == null) ||
(createController == null && controller != null),
Expand All @@ -402,16 +412,17 @@ class DevToolsScreen<C> {
if (controllerLocal != null) {
return Provider<C>.value(value: controllerLocal);
}
return Provider<C>(create: (_) => createController!());
return Provider<C>(create: (_) => createController!(routerDelegate));
}
}

/// A [WidgetBuilder] that takes an additional map of URL query parameters and
/// args.
/// args, as well a state not included in the URL.
typedef UrlParametersBuilder = Widget Function(
BuildContext,
String?,
Map<String, String?>,
DevToolsNavigationState?,
);

/// Displays the checked mode banner in the bottom end corner instead of the
Expand Down Expand Up @@ -566,52 +577,54 @@ List<DevToolsScreen> get defaultScreens {
return <DevToolsScreen>[
DevToolsScreen<InspectorController>(
const InspectorScreen(),
createController: () => InspectorController(
createController: (_) => InspectorController(
inspectorTree: InspectorTreeController(),
detailsTree: InspectorTreeController(),
treeType: FlutterTreeType.widget,
),
),
DevToolsScreen<PerformanceController>(
const PerformanceScreen(),
createController: () => PerformanceController(),
createController: (_) => PerformanceController(),
supportsOffline: true,
),
DevToolsScreen<ProfilerScreenController>(
const ProfilerScreen(),
createController: () => ProfilerScreenController(),
createController: (_) => ProfilerScreenController(),
supportsOffline: true,
),
DevToolsScreen<MemoryController>(
const MemoryScreen(),
createController: () => MemoryController(),
createController: (_) => MemoryController(),
),
DevToolsScreen<DebuggerController>(
const DebuggerScreen(),
createController: () => DebuggerController(),
createController: (routerDelegate) => DebuggerController(
routerDelegate: routerDelegate,
),
),
DevToolsScreen<NetworkController>(
const NetworkScreen(),
createController: () => NetworkController(),
createController: (_) => NetworkController(),
),
DevToolsScreen<LoggingController>(
const LoggingScreen(),
createController: () => LoggingController(),
createController: (_) => LoggingController(),
),
DevToolsScreen<void>(const ProviderScreen(), createController: () {}),
DevToolsScreen<void>(const ProviderScreen(), createController: (_) {}),
DevToolsScreen<AppSizeController>(
const AppSizeScreen(),
createController: () => AppSizeController(),
createController: (_) => AppSizeController(),
),
DevToolsScreen<VMDeveloperToolsController>(
const VMDeveloperToolsScreen(),
createController: () => VMDeveloperToolsController(),
createController: (_) => VMDeveloperToolsController(),
),
// Show the sample DevTools screen.
if (debugEnableSampleScreen && (kDebugMode || kProfileMode))
DevToolsScreen<ExampleController>(
const ExampleConditionalScreen(),
createController: () => ExampleController(),
createController: (_) => ExampleController(),
supportsOffline: true,
),
];
Expand Down
1 change: 1 addition & 0 deletions packages/devtools_app/lib/src/framework/scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ class DevToolsScaffoldState extends State<DevToolsScaffold>
routerDelegate.navigateIfNotCurrent(
_currentScreen.screenId,
routerDelegate.currentConfiguration?.args,
routerDelegate.currentConfiguration?.state,
);
});
});
Expand Down
96 changes: 51 additions & 45 deletions packages/devtools_app/lib/src/screens/debugger/codeview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import 'debugger_controller.dart';
import 'debugger_model.dart';
import 'file_search.dart';
import 'key_sets.dart';
import 'program_explorer_model.dart';
import 'variables.dart';

final debuggerCodeViewSearchKey =
Expand Down Expand Up @@ -168,56 +167,65 @@ class _CodeViewState extends State<CodeView>
return;
}

if (!verticalController.hasAttachedControllers) {
// TODO(devoncarew): I'm uncertain why this occurs.
log('LinkedScrollControllerGroup has no attached controllers');
return;
}
final line = widget.codeViewController.scriptLocation.value?.location?.line;
if (line == null) {
// Don't scroll to top if we're just rebuilding the code view for the
// same script.
if (_lastScriptRef?.uri != scriptRef?.uri) {
// Default to scrolling to the top of the script.
void updateScrollPositionImpl() {
if (!verticalController.hasAttachedControllers) {
// TODO(devoncarew): I'm uncertain why this occurs.
log('LinkedScrollControllerGroup has no attached controllers');
return;
}
final line =
widget.codeViewController.scriptLocation.value?.location?.line;
if (line == null) {
// Don't scroll to top if we're just rebuilding the code view for the
// same script.
if (_lastScriptRef?.uri != scriptRef?.uri) {
// Default to scrolling to the top of the script.
if (animate) {
unawaited(
verticalController.animateTo(
0,
duration: longDuration,
curve: defaultCurve,
),
);
} else {
verticalController.jumpTo(0);
}
_lastScriptRef = scriptRef;
}
return;
}

final position = verticalController.position;
final extent = position.extentInside;

// TODO(devoncarew): Adjust this so we don't scroll if we're already in the
// middle third of the screen.
final lineCount = parsedScript?.lineCount;
if (lineCount != null && lineCount * CodeView.rowHeight > extent) {
final lineIndex = line - 1;
final scrollPosition = lineIndex * CodeView.rowHeight -
((extent - CodeView.rowHeight) / 2);
if (animate) {
unawaited(
verticalController.animateTo(
0,
scrollPosition,
duration: longDuration,
curve: defaultCurve,
),
);
} else {
verticalController.jumpTo(0);
verticalController.jumpTo(scrollPosition);
}
_lastScriptRef = scriptRef;
}
return;
_lastScriptRef = scriptRef;
}

final position = verticalController.position;
final extent = position.extentInside;

// TODO(devoncarew): Adjust this so we don't scroll if we're already in the
// middle third of the screen.
final lineCount = parsedScript?.lineCount;
if (lineCount != null && lineCount * CodeView.rowHeight > extent) {
final lineIndex = line - 1;
final scrollPosition =
lineIndex * CodeView.rowHeight - ((extent - CodeView.rowHeight) / 2);
if (animate) {
unawaited(
verticalController.animateTo(
scrollPosition,
duration: longDuration,
curve: defaultCurve,
),
);
} else {
verticalController.jumpTo(scrollPosition);
}
}
_lastScriptRef = scriptRef;
verticalController.hasAttachedControllers
? updateScrollPositionImpl()
: WidgetsBinding.instance.addPostFrameCallback(
(_) => updateScrollPositionImpl(),
);
}

void _onPressed(int line) {
Expand Down Expand Up @@ -785,12 +793,10 @@ class _LinesState extends State<Lines> with AutoDisposeMixin {
itemBuilder: (context, index) {
final lineNum = index + 1;
final isPausedLine = pausedLine == lineNum;
return ValueListenableBuilder<VMServiceObjectNode?>(
valueListenable: widget
.codeViewController.programExplorerController.outlineSelection,
builder: (context, outlineNode, _) {
final isFocusedLine =
(outlineNode?.location?.location?.line ?? -1) == lineNum;
return ValueListenableBuilder<int>(
valueListenable: widget.codeViewController.focusLine,
builder: (context, focusLine, _) {
final isFocusedLine = focusLine == lineNum;
return LineItem(
lineContents: widget.lines[index],
pausedFrame: isPausedLine ? widget.pausedFrame : null,
Expand Down
Loading