Skip to content
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
59 changes: 41 additions & 18 deletions lib/core/sdui/sdui_form_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,8 @@ class SduiFormBuilderState extends material.State<SduiFormBuilder> {

Future<void> _pickFile(SduiFormField field) async {
final picker = widget.filePicker;
final path = picker != null
? await picker(field)
: (await openFile())?.path;
final path =
picker != null ? await picker(field) : (await openFile())?.path;
if (path == null || !mounted) return;
_textControllers[field.id]?.text = path;
_notifyChanged();
Expand Down Expand Up @@ -199,28 +198,52 @@ class SduiFormBuilderState extends material.State<SduiFormBuilder> {
),
);
case SduiFieldType.select:
final options = field.options;
final current = _selectValues[field.id] ??
(options.isNotEmpty ? options.first.value : '');
return material.Column(
crossAxisAlignment: material.CrossAxisAlignment.stretch,
children: [
Text(field.label).small().semiBold(),
const Gap(4),
material.DropdownButtonFormField<String>(
initialValue: _selectValues[field.id],
items: [
for (final opt in field.options)
material.DropdownMenuItem(
value: opt.value,
child: material.Text(opt.label),
),
],
onChanged: (v) {
setState(() => _selectValues[field.id] = v);
_notifyChanged();
},
material.FormField<String>(
initialValue: current,
validator: field.required
? (v) =>
(v == null || v.isEmpty) ? '${field.label} is required' : null
? (v) => (v == null || v.isEmpty)
? '${field.label} is required'
: null
: null,
builder: (state) {
final value = state.value ?? current;
return material.Column(
crossAxisAlignment: material.CrossAxisAlignment.stretch,
children: [
QueryaDropdown<String>(
value: value.isEmpty && options.isNotEmpty
? options.first.value
: value,
expandToParent: true,
items: [
for (final opt in options)
QueryaDropdownItem<String>(
value: opt.value,
label: opt.label,
),
],
onSelected: (v) {
final next = v ?? value;
setState(() => _selectValues[field.id] = next);
state.didChange(next);
_notifyChanged();
},
),
if (state.hasError) ...[
const Gap(4),
Text(state.errorText!).xSmall().muted(),
],
],
);
},
),
],
);
Expand Down
3 changes: 2 additions & 1 deletion lib/core/sdui/sdui_form_schema.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class SduiFormField {
if (item is Map<String, dynamic>) {
options.add(SduiSelectOption.fromJson(item));
} else if (item is Map) {
options.add(SduiSelectOption.fromJson(Map<String, dynamic>.from(item)));
options
.add(SduiSelectOption.fromJson(Map<String, dynamic>.from(item)));
} else if (item != null) {
options.add(SduiSelectOption(value: '$item', label: '$item'));
}
Expand Down
21 changes: 14 additions & 7 deletions lib/core/sdui/sdui_tree_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,19 @@ class SduiTreeBuilderState extends material.State<SduiTreeBuilder> {
physics: widget.maxHeight == null
? const material.NeverScrollableScrollPhysics()
: const material.ClampingScrollPhysics(),
itemExtent: _rowExtent,
itemExtent: rows.any((r) => r.isError) ? null : _rowExtent,
itemCount: rows.length,
itemBuilder: (context, index) {
final row = rows[index];
if (row.isError) {
return material.Padding(
return TreeLoadError(
title: 'Could not expand',
message: row.error!,
detailFontSize: 10,
padding: material.EdgeInsets.only(
left: 36.0 + row.depth * QueryaTreeTokens.indent,
),
child: material.Align(
alignment: material.Alignment.centerLeft,
child: Text(row.error!).muted().xSmall(),
top: 2,
bottom: 2,
),
);
}
Expand Down Expand Up @@ -213,7 +214,7 @@ class SduiTreeBuilderState extends material.State<SduiTreeBuilder> {
final rowLeft =
8.0 + depth * QueryaTreeTokens.indent + (canExpand ? 0 : 4.0);

return material.InkWell(
final row = material.InkWell(
onTap: () {
if (isBrowsable) {
widget.onNodeSelected?.call(node);
Expand Down Expand Up @@ -284,6 +285,12 @@ class SduiTreeBuilderState extends material.State<SduiTreeBuilder> {
),
),
);
if (!canExpand) return row;
return material.Semantics(
button: true,
expanded: isExpanded,
child: row,
);
}

String _resolveNodeKind(SduiTreeNode node) {
Expand Down
3 changes: 2 additions & 1 deletion lib/core/sdui/sdui_tree_schema.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,5 @@ class SduiTreeSchema {
}

/// Loads children for an expandable node (`fetchTreeChildren` RPC).
typedef SduiFetchTreeChildren = Future<List<SduiTreeNode>> Function(String nodeId);
typedef SduiFetchTreeChildren = Future<List<SduiTreeNode>> Function(
String nodeId);
15 changes: 11 additions & 4 deletions lib/features/connections/connections_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import 'package:flutter/material.dart' as material
Expanded,
CircularProgressIndicator,
Material,
Semantics,
StatelessWidget,
Colors,
Tooltip,
Expand Down Expand Up @@ -349,11 +350,17 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
_expandedConnections.remove(id);
});
if (conn.type == 'postgresql') {
PostgresService.instance.interrupt(conn, database: conn.databaseName ?? 'postgres', mode: PgSessionMode.readOnly);
PostgresService.instance.interrupt(conn, database: conn.databaseName ?? 'postgres', mode: PgSessionMode.readWrite);
PostgresService.instance.interrupt(conn,
database: conn.databaseName ?? 'postgres',
mode: PgSessionMode.readOnly);
PostgresService.instance.interrupt(conn,
database: conn.databaseName ?? 'postgres',
mode: PgSessionMode.readWrite);
} else if (conn.type == 'mysql') {
MysqlService.instance.interrupt(conn, database: conn.databaseName ?? '', mode: MysqlSessionMode.readOnly);
MysqlService.instance.interrupt(conn, database: conn.databaseName ?? '', mode: MysqlSessionMode.readWrite);
MysqlService.instance.interrupt(conn,
database: conn.databaseName ?? '', mode: MysqlSessionMode.readOnly);
MysqlService.instance.interrupt(conn,
database: conn.databaseName ?? '', mode: MysqlSessionMode.readWrite);
} else if (conn.type == 'sqlite') {
SqliteService.instance.interrupt(conn, mode: SqliteSessionMode.readOnly);
SqliteService.instance.interrupt(conn, mode: SqliteSessionMode.readWrite);
Expand Down
37 changes: 22 additions & 15 deletions lib/features/connections/connections_panel_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> {
_error = null;
});
try {
final schema =
await ExtensionDriverSession.instance.getSchemaTree(widget.connection);
final schema = await ExtensionDriverSession.instance
.getSchemaTree(widget.connection);
if (!mounted) return;
setState(() {
_schema = schema;
Expand Down Expand Up @@ -174,19 +174,25 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> {
children: [
material.MouseRegion(
cursor: material.SystemMouseCursors.click,
child: material.InkWell(
onTap: _toggle,
borderRadius: material.BorderRadius.circular(4),
child: material.Padding(
padding: const material.EdgeInsets.all(2),
child: material.AnimatedRotation(
turns: widget.isExpanded ? 0.25 : 0,
duration: context.motionDuration(QueryaMotion.treeExpand),
curve: context.motionCurve(QueryaMotion.treeExpandCurve),
child: material.Icon(
QueryaIcons.expandClosed,
size: QueryaIconSizes.sidebarExpand,
color: theme.colorScheme.mutedForeground,
child: material.Semantics(
button: true,
expanded: widget.isExpanded,
child: material.InkWell(
onTap: _toggle,
borderRadius: material.BorderRadius.circular(4),
child: material.Padding(
padding: const material.EdgeInsets.all(2),
child: material.AnimatedRotation(
turns: widget.isExpanded ? 0.25 : 0,
duration:
context.motionDuration(QueryaMotion.treeExpand),
curve:
context.motionCurve(QueryaMotion.treeExpandCurve),
child: material.Icon(
QueryaIcons.expandClosed,
size: QueryaIconSizes.sidebarExpand,
color: theme.colorScheme.mutedForeground,
),
),
),
),
Expand Down Expand Up @@ -288,6 +294,7 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> {
)
else if (_error != null)
TreeLoadError(
title: 'Could not load extension tree',
message: _error!,
padding: const material.EdgeInsets.only(
left: 28,
Expand Down
33 changes: 19 additions & 14 deletions lib/features/connections/connections_panel_mongo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -191,19 +191,25 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> {
// Expand/collapse arrow
material.MouseRegion(
cursor: material.SystemMouseCursors.click,
child: material.InkWell(
onTap: _toggle,
borderRadius: material.BorderRadius.circular(4),
child: material.Padding(
padding: const material.EdgeInsets.all(2),
child: material.AnimatedRotation(
turns: _expanded ? 0.25 : 0,
duration: context.motionDuration(QueryaMotion.treeExpand),
curve: context.motionCurve(QueryaMotion.treeExpandCurve),
child: material.Icon(
QueryaIcons.expandClosed,
size: QueryaIconSizes.sidebarExpand,
color: theme.colorScheme.mutedForeground,
child: material.Semantics(
button: true,
expanded: _expanded,
child: material.InkWell(
onTap: _toggle,
borderRadius: material.BorderRadius.circular(4),
child: material.Padding(
padding: const material.EdgeInsets.all(2),
child: material.AnimatedRotation(
turns: _expanded ? 0.25 : 0,
duration:
context.motionDuration(QueryaMotion.treeExpand),
curve:
context.motionCurve(QueryaMotion.treeExpandCurve),
child: material.Icon(
QueryaIcons.expandClosed,
size: QueryaIconSizes.sidebarExpand,
color: theme.colorScheme.mutedForeground,
),
),
),
),
Expand Down Expand Up @@ -285,7 +291,6 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> {
TreeLoadError(
title: 'Could not load databases',
message: _error!,
showTitleRow: true,
detailFontSize: 10,
padding: const material.EdgeInsets.only(
left: 28,
Expand Down
36 changes: 23 additions & 13 deletions lib/features/connections/connections_panel_mysql.dart
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,25 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> {
children: [
material.MouseRegion(
cursor: material.SystemMouseCursors.click,
child: material.InkWell(
onTap: _toggle,
borderRadius: material.BorderRadius.circular(4),
child: material.Padding(
padding: const material.EdgeInsets.all(2),
child: material.AnimatedRotation(
turns: _expanded ? 0.25 : 0,
duration: context.motionDuration(QueryaMotion.treeExpand),
curve: context.motionCurve(QueryaMotion.treeExpandCurve),
child: material.Icon(
QueryaIcons.expandClosed,
size: QueryaIconSizes.sidebarExpand,
color: theme.colorScheme.mutedForeground,
child: material.Semantics(
button: true,
expanded: _expanded,
child: material.InkWell(
onTap: _toggle,
borderRadius: material.BorderRadius.circular(4),
child: material.Padding(
padding: const material.EdgeInsets.all(2),
child: material.AnimatedRotation(
turns: _expanded ? 0.25 : 0,
duration:
context.motionDuration(QueryaMotion.treeExpand),
curve:
context.motionCurve(QueryaMotion.treeExpandCurve),
child: material.Icon(
QueryaIcons.expandClosed,
size: QueryaIconSizes.sidebarExpand,
color: theme.colorScheme.mutedForeground,
),
),
),
),
Expand Down Expand Up @@ -246,6 +252,7 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> {
),
if (_error != null)
TreeLoadError(
title: 'Could not load databases',
message: _error!,
padding: const material.EdgeInsets.only(
left: 28,
Expand Down Expand Up @@ -457,6 +464,7 @@ class _MysqlDatabaseNodeState extends State<_MysqlDatabaseNode> {
color: theme.colorScheme.foreground,
),
verticalPadding: 4,
expanded: _expanded,
onTap: _toggle,
connection: widget.connection,
onContextRefresh: _loadTables,
Expand Down Expand Up @@ -490,6 +498,7 @@ class _MysqlDatabaseNodeState extends State<_MysqlDatabaseNode> {
)
else if (_error != null)
TreeLoadError(
title: 'Could not load tables',
message: _error!,
onRetry: _loadTables,
),
Expand Down Expand Up @@ -648,6 +657,7 @@ class _MysqlObjectGroupState extends State<_MysqlObjectGroup> {
fontSize: 11,
color: theme.colorScheme.mutedForeground,
),
expanded: _expanded,
onTap: () => setState(() => _expanded = !_expanded),
connection: widget.connection,
onContextRefresh: widget.onRefresh,
Expand Down
Loading
Loading