Skip to content

Commit 72ad35b

Browse files
authored
Allow right click options (version 0.1.5) (#4)
* Allow right click options * `NodeWidget` is now moved to this package * Use gradient scroll view * Use `DebugTreeView` instead of the generic `TreeView` * Code cleanup * Use `searchReference` along with the `link`
1 parent 96823f5 commit 72ad35b

13 files changed

+46716
-45547
lines changed

extension/devtools/build/flutter_bootstrap.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extension/devtools/build/flutter_service_worker.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
33
const TEMP = 'flutter-temp-cache';
44
const CACHE_NAME = 'flutter-app-cache';
55

6-
const RESOURCES = {"flutter_bootstrap.js": "c43f6b3d6cb22e11f4307ce2a12d1bbb",
7-
"version.json": "58c669002200e69eff81e37902cb1971",
6+
const RESOURCES = {"flutter_bootstrap.js": "2d275fb884f93fa49b29a9c7166c846d",
7+
"version.json": "0a388a4d54ecb5fc56daaf2a8e2b7923",
88
"index.html": "aa6f466ba4f6154a3e7ad6465ec3796b",
99
"/": "aa6f466ba4f6154a3e7ad6465ec3796b",
10-
"main.dart.js": "f870985b1af898cd1435f7a0908d79e4",
10+
"main.dart.js": "5756642eb2a3b4ec1066498d89ffbb59",
1111
"flutter.js": "383e55f7f3cce5be08fcf1f3881f585c",
1212
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
1313
"icons/Icon-192.png": "ac9a721a12bbc803b44f645561ecb1e1",

extension/devtools/build/main.dart.js

Lines changed: 46190 additions & 45518 deletions
Large diffs are not rendered by default.

extension/devtools/build/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"app_name":"flutterflow_debug_panel","version":"0.1.3","package_name":"flutterflow_debug_panel"}
1+
{"app_name":"flutterflow_debug_panel","version":"0.1.5","package_name":"flutterflow_debug_panel"}

extension/devtools/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
name: flutterflow_debug_panel
2-
version: 0.1.3
2+
version: 0.1.5
33
issueTracker: https://github.com/FlutterFlow/flutterflow-issues/issues
44
materialIconCodePoint: "0xe115"

lib/src/pages/debug_panel_page.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:async';
22

3+
import 'package:flutter/services.dart';
34
import 'package:flutterflow_debug_panel/src/utils/debug_utils.dart';
45
import 'package:flutterflow_debug_panel/src/widgets/debug_variables_panel.dart';
56
import 'package:devtools_extensions/devtools_extensions.dart';
@@ -35,20 +36,26 @@ class _DebugPanelPageState extends State<DebugPanelPage> {
3536
@override
3637
void initState() {
3738
super.initState();
39+
// Disable the browser's default context menu, so that we can show our
40+
// custom right-click menu on the variables.
41+
BrowserContextMenu.disableContextMenu();
3842
_appEventHandler();
3943
}
4044

4145
@override
4246
void dispose() {
4347
extensionEventSubscription.cancel();
4448
vmService.dispose();
49+
// Re-enable the browser's default context menu.
50+
BrowserContextMenu.enableContextMenu();
4551
super.dispose();
4652
}
4753

4854
@override
4955
Widget build(BuildContext context) => ChangeNotifierProvider(
5056
create: (context) => variableDebugData,
5157
child: DebugVariablesPanel(
58+
listGradientColor: Theme.of(context).scaffoldBackgroundColor,
5259
onEvent: (name, params) {
5360
if (kDebugMode) {
5461
debugPrint('$name, $params');

lib/src/widgets/debug_tree_view.dart

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutterflow_debug_panel/src/widgets/flutterflow_gradient_scroll_view.dart';
3+
import 'package:flutterflow_tree_view/flutterflow_tree_view.dart';
4+
5+
/// Tree view with collapsible and expandable nodes.
6+
class DebugTreeView extends StatelessWidget {
7+
/// Constructs a tree view widget.
8+
///
9+
/// - [nodes] parameter is a required list of [TreeNode] objects that represent the nodes in the tree.
10+
/// - [treeController] parameter is an optional [TreeController] object that controls the behavior of the tree view.
11+
/// - [nodeBuilder] parameter is a required function that builds a widget for each tree node.
12+
DebugTreeView({
13+
super.key,
14+
required List<TreeNode> nodes,
15+
required this.treeController,
16+
required this.nodeBuilder,
17+
this.listPadding,
18+
this.listGradientColor,
19+
}) : nodes = copyTreeNodes(nodes);
20+
21+
/// List of root level tree nodes.
22+
final List<TreeNode> nodes;
23+
24+
/// Builder function to create a widget for each tree node.
25+
final Widget Function(BuildContext context, FlattenTreeNode flattenedNode)
26+
nodeBuilder;
27+
28+
/// Tree controller to manage the tree state.
29+
final TreeController treeController;
30+
31+
/// Padding for the list view.
32+
final EdgeInsets? listPadding;
33+
34+
/// Color for the gradient background of the list view.
35+
final Color? listGradientColor;
36+
37+
@override
38+
Widget build(BuildContext context) {
39+
final flattenedTreeNode = FlattenTreeNode.getFlattenedTree(
40+
nodes,
41+
treeController,
42+
);
43+
return FlutterFlowGradientScrollView(
44+
gradientHeight: 100,
45+
gradientColor: listGradientColor,
46+
child: (controller) => ListView.builder(
47+
controller: controller,
48+
padding: listPadding ?? EdgeInsets.zero,
49+
itemCount: flattenedTreeNode.length,
50+
itemBuilder: (context, index) =>
51+
nodeBuilder(context, flattenedTreeNode[index]),
52+
),
53+
);
54+
}
55+
}

lib/src/widgets/debug_variables_panel.dart

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ class DebugVariablesPanel extends StatefulWidget {
2020
const DebugVariablesPanel({
2121
super.key,
2222
required this.onEvent,
23+
this.listGradientColor,
2324
});
2425

2526
final Function(String name, Map<String, dynamic>? params) onEvent;
2627

28+
final Color? listGradientColor;
29+
2730
@override
2831
State<DebugVariablesPanel> createState() => _DebugVariablesPanelState();
2932
}
@@ -41,14 +44,22 @@ class _DebugVariablesPanelState extends State<DebugVariablesPanel> {
4144
void initState() {
4245
super.initState();
4346
_treeController = TreeController(
44-
onNodeToggled: (name) {
47+
onNodeToggled: (name, [isAllExpanded]) {
4548
if (mounted) {
4649
setState(() {});
4750
}
48-
logEvent(
49-
'debug-panel-toggle-section',
50-
{'name': name},
51-
);
51+
52+
if (name != null) {
53+
logEvent(
54+
'debug-panel-toggle-section',
55+
{'name': name},
56+
);
57+
} else if (isAllExpanded != null) {
58+
logEvent(
59+
'debug-panel-${isAllExpanded ? 'expand' : 'collapse'}-all',
60+
{},
61+
);
62+
}
5263
},
5364
onTreeEvent: (event) => widget.onEvent(event.name, event.params),
5465
);
@@ -188,9 +199,43 @@ class _DebugVariablesPanelState extends State<DebugVariablesPanel> {
188199
],
189200
),
190201
)
191-
: NarrowModal(
192-
treeController: _treeController,
193-
narrowModalSections: filteredDebugTree,
202+
: Stack(
203+
children: [
204+
NarrowModal(
205+
treeController: _treeController,
206+
narrowModalSections: filteredDebugTree,
207+
listGradientColor: widget.listGradientColor,
208+
),
209+
Align(
210+
alignment: Alignment.topRight,
211+
child: Padding(
212+
padding: const EdgeInsets.only(top: 2.0),
213+
child: InkWell(
214+
borderRadius: BorderRadius.circular(8.0),
215+
onTap: () =>
216+
_treeController.allNodesExpanded
217+
? _treeController.collapseAll()
218+
: _treeController.expandAll(),
219+
child: Padding(
220+
padding: const EdgeInsets.symmetric(
221+
horizontal: kPadding8px,
222+
vertical: kPadding2px,
223+
),
224+
child: Text(
225+
_treeController.allNodesExpanded
226+
? 'Collapse all'
227+
: 'Expand all',
228+
style: productSans(
229+
context,
230+
size: kFontSize12px,
231+
color: context.theme.secondaryText,
232+
),
233+
),
234+
),
235+
),
236+
),
237+
),
238+
],
194239
),
195240
),
196241
],
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter/scheduler.dart';
3+
import 'package:flutterflow_debug_panel/src/themes/flutter_flow_default_theme.dart';
4+
import 'package:flutterflow_debug_panel/src/utils/ff_utils.dart';
5+
6+
/// A scrollable widget that displays a gradient at the top and bottom.
7+
class FlutterFlowGradientScrollView extends StatefulWidget {
8+
/// Creates a scrollable widget that displays a gradient at the top and bottom
9+
/// based on the scroll position.
10+
///
11+
/// * [child] parameter is the child widget that will be scrolled.
12+
///
13+
/// * [gradientColor] parameter is the color of the gradient. If not provided,
14+
/// it will use the panel color.
15+
///
16+
/// * [gradientHeight] parameter is the height of the gradient. Default is 50.0.
17+
const FlutterFlowGradientScrollView({
18+
super.key,
19+
required this.child,
20+
this.gradientColor,
21+
this.gradientHeight = 50.0,
22+
});
23+
24+
/// The child widget that will be scrolled.
25+
final ScrollView Function(ScrollController controller) child;
26+
27+
/// The color of the gradient. If not provided, it will use the panel color.
28+
final Color? gradientColor;
29+
30+
/// The height of the gradient. Default is 50.0.
31+
final double gradientHeight;
32+
33+
@override
34+
State<FlutterFlowGradientScrollView> createState() =>
35+
_FlutterFlowGradientScrollViewState();
36+
}
37+
38+
class _FlutterFlowGradientScrollViewState
39+
extends State<FlutterFlowGradientScrollView> {
40+
var _showStartGradient = false;
41+
var _showEndGradient = false;
42+
double? _maxScrollExtent;
43+
final _scrollController = ScrollController();
44+
45+
@override
46+
Widget build(BuildContext context) {
47+
// This is a workaround to get the max scroll extent after the first frame
48+
// to set the initial state of the gradients, and to update the state when
49+
// the scroll length changes.
50+
SchedulerBinding.instance.addPostFrameCallback((_) {
51+
if (_scrollController.positions.isNotEmpty &&
52+
_scrollController.hasClients) {
53+
if (_maxScrollExtent == null ||
54+
_maxScrollExtent != _scrollController.position.maxScrollExtent) {
55+
_maxScrollExtent = _scrollController.position.maxScrollExtent;
56+
_showEndGradient = _showStartGradient =
57+
_scrollController.position.maxScrollExtent > 0;
58+
setState(() {});
59+
}
60+
}
61+
});
62+
63+
final gradientColor = widget.gradientColor ?? context.theme.panelColor;
64+
return Stack(
65+
children: [
66+
NotificationListener<ScrollNotification>(
67+
onNotification: (scrollInfo) {
68+
final extentBefore = scrollInfo.metrics.extentBefore;
69+
final extentAfter = scrollInfo.metrics.extentAfter;
70+
var updatedShowStartGradient = false;
71+
var updatedShowEndGradient = false;
72+
if (extentBefore > 0) {
73+
updatedShowStartGradient = true;
74+
} else {
75+
updatedShowStartGradient = false;
76+
}
77+
if (extentAfter > 0) {
78+
updatedShowEndGradient = true;
79+
} else {
80+
updatedShowEndGradient = false;
81+
}
82+
if (updatedShowStartGradient != _showStartGradient ||
83+
updatedShowEndGradient != _showEndGradient) {
84+
setState(() {
85+
_showStartGradient = updatedShowStartGradient;
86+
_showEndGradient = updatedShowEndGradient;
87+
});
88+
}
89+
return true;
90+
},
91+
child: widget.child(_scrollController),
92+
),
93+
IgnorePointer(
94+
child: Column(
95+
children: [
96+
AnimatedOpacity(
97+
duration: 300.millis,
98+
opacity: _scrollController.positions.isNotEmpty &&
99+
_scrollController.offset > 0 &&
100+
_showStartGradient
101+
? 1
102+
: 0,
103+
child: Container(
104+
height: widget.gradientHeight,
105+
decoration: BoxDecoration(
106+
gradient: LinearGradient(
107+
begin: Alignment.topCenter,
108+
end: Alignment.bottomCenter,
109+
colors: [
110+
gradientColor,
111+
gradientColor.withOpacity(0),
112+
],
113+
),
114+
),
115+
),
116+
),
117+
const Spacer(),
118+
AnimatedOpacity(
119+
duration: 300.millis,
120+
opacity: _showEndGradient ? 1 : 0,
121+
child: Container(
122+
height: widget.gradientHeight,
123+
decoration: BoxDecoration(
124+
gradient: LinearGradient(
125+
begin: Alignment.topCenter,
126+
end: Alignment.bottomCenter,
127+
colors: [
128+
gradientColor.withOpacity(0),
129+
gradientColor,
130+
],
131+
),
132+
),
133+
),
134+
),
135+
],
136+
),
137+
),
138+
],
139+
);
140+
}
141+
}

0 commit comments

Comments
 (0)