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
37 changes: 7 additions & 30 deletions lib/core/sdui/sdui_tree_builder.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:flutter/material.dart' as material;
import 'package:querya_desktop/core/sdui/sdui_tree_schema.dart';
import 'package:querya_desktop/core/ui/querya_icon_sizes.dart';
import 'package:querya_desktop/core/ui/querya_icons.dart';
import 'package:querya_desktop/shared/widgets/widgets.dart';

/// Renders a sidebar-style tree from an SDUI schema with lazy expansion.
Expand Down Expand Up @@ -224,8 +226,11 @@ class SduiTreeBuilderState extends material.State<SduiTreeBuilder> {
)
else
material.Icon(
_iconFor(node),
size: 16,
QueryaIcons.sduiNodeIcon(
node.icon,
expandable: node.expandable,
),
size: QueryaIconSizes.sduiNode,
),
const Gap(8),
material.Expanded(
Expand All @@ -252,32 +257,4 @@ class SduiTreeBuilderState extends material.State<SduiTreeBuilder> {
final parts = node.id.split('.');
return parts.isNotEmpty ? parts.first : '';
}

material.IconData _iconFor(SduiTreeNode node) {
switch (node.icon) {
case 'database':
return material.Icons.storage_outlined;
case 'table':
return material.Icons.table_chart_outlined;
case 'view':
case 'eye':
return material.Icons.visibility_outlined;
case 'folder':
case 'folder-table':
return material.Icons.folder_outlined;
case 'folder-eye':
return material.Icons.folder_special_outlined;
case 'folder-book':
case 'book':
return material.Icons.menu_book_outlined;
case 'columns':
return material.Icons.view_column_outlined;
case 'archive':
return material.Icons.inventory_2_outlined;
default:
return node.expandable
? material.Icons.folder_outlined
: material.Icons.insert_drive_file_outlined;
}
}
}
23 changes: 23 additions & 0 deletions lib/core/ui/querya_icon_sizes.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// Semantic icon sizes for connection trees and shared chrome.
abstract final class QueryaIconSizes {
/// Leaf row icon (table name, view name, …).
static const double treeLeaf = 12;

/// Group / schema / default tree row icon.
static const double treeGroup = 13;

/// Expand chevron in tree rows.
static const double treeExpand = 13;

/// Database / connection-level tree nodes.
static const double treeConnection = 14;

/// Inline tree error indicator.
static const double treeError = 14;

/// SDUI explorer tree nodes.
static const double sduiNode = 16;

/// Menu / dialog leading icons.
static const double menuLeading = 18;
}
90 changes: 90 additions & 0 deletions lib/core/ui/querya_icons.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import 'package:flutter/material.dart' as material;

/// Shared Material icon registry for connection trees and chrome.
abstract final class QueryaIcons {
// -- Tree entity icons (rounded, aligned across PG / MySQL / SQLite) --

static const material.IconData expandClosed =
material.Icons.chevron_right_rounded;

static const material.IconData databasesFolder =
material.Icons.dns_rounded;
static const material.IconData database = material.Icons.storage_rounded;
static const material.IconData schemasFolder =
material.Icons.account_tree_rounded;
static const material.IconData schema = material.Icons.diamond_rounded;
static const material.IconData extension = material.Icons.extension_rounded;
static const material.IconData publicSchema = material.Icons.public_rounded;

static const material.IconData tableGroup =
material.Icons.table_chart_rounded;
static const material.IconData tableLeaf = material.Icons.grid_on_rounded;
static const material.IconData viewGroup = material.Icons.view_agenda_rounded;
static const material.IconData viewLeaf = material.Icons.view_week_rounded;
static const material.IconData materializedViewGroup =
material.Icons.dynamic_feed_rounded;
static const material.IconData functionGroup =
material.Icons.functions_rounded;
static const material.IconData functionLeaf = material.Icons.code_rounded;
static const material.IconData sequence =
material.Icons.format_list_numbered_rounded;
static const material.IconData indexes = material.Icons.table_rows_rounded;
static const material.IconData triggers = material.Icons.bolt_rounded;
static const material.IconData types = material.Icons.category_rounded;

static const material.IconData treeError =
material.Icons.error_outline_rounded;
static const material.IconData folder = material.Icons.folder_rounded;

// -- Built-in connection types --

static material.IconData connectionIcon(String type) => switch (type) {
'mongodb' => material.Icons.eco_rounded,
'postgresql' => material.Icons.storage_rounded,
'mysql' => material.Icons.table_chart_rounded,
'redis' => material.Icons.memory_rounded,
'sqlite' => material.Icons.folder_open_rounded,
_ => material.Icons.extension_rounded,
};

static String? connectionAsset(String type) => switch (type) {
'postgresql' => 'assets/images/postgresql_icon.png',
'mysql' => 'assets/images/mysql_icon.png',
'redis' => 'assets/images/redis_icon.png',
'mongodb' => 'assets/images/mongodb_icon.png',
_ => null,
};

// -- SDUI tree nodes (rounded to match native trees) --

static material.IconData sduiNodeIcon(
String? icon, {
required bool expandable,
}) {
switch (icon) {
case 'database':
return database;
case 'table':
return tableGroup;
case 'view':
case 'eye':
return viewGroup;
case 'folder':
case 'folder-table':
return folder;
case 'folder-eye':
return material.Icons.folder_special_rounded;
case 'folder-book':
case 'book':
return material.Icons.menu_book_rounded;
case 'columns':
return material.Icons.view_column_rounded;
case 'archive':
return material.Icons.inventory_2_rounded;
default:
return expandable
? folder
: material.Icons.insert_drive_file_rounded;
}
}
}
56 changes: 17 additions & 39 deletions lib/features/connections/connections_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import 'package:flutter/material.dart' as material
Colors,
Tooltip,
Color,
SelectableText,
Padding,
Widget,
Navigator,
Expand All @@ -67,6 +66,8 @@ import 'package:querya_desktop/core/sdui/sdui_tree_schema.dart';
import 'package:querya_desktop/core/storage/folders_storage.dart';
import 'package:querya_desktop/core/storage/local_db.dart';
import 'package:querya_desktop/core/theme/querya_typography.dart';
import 'package:querya_desktop/core/ui/querya_icon_sizes.dart';
import 'package:querya_desktop/core/ui/querya_icons.dart';
import 'package:querya_desktop/core/motion/querya_animated_expand.dart';
import 'package:querya_desktop/core/motion/querya_motion.dart';
import 'package:querya_desktop/core/motion/querya_motion_context.dart';
Expand Down Expand Up @@ -395,29 +396,6 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
}
}

/// Icon for a connection type (matches New Connection dialog).
material.IconData _iconForType(String type) {
return switch (type) {
'mongodb' => material.Icons.eco_rounded,
'postgresql' => material.Icons.storage_rounded,
'mysql' => material.Icons.table_chart_rounded,
'redis' => material.Icons.memory_rounded,
'sqlite' => material.Icons.folder_open_rounded,
_ => material.Icons.extension_rounded,
};
}

/// Asset path for connection type logo (null = use icon).
static String? _iconAssetForType(String type) {
return switch (type) {
'postgresql' => 'assets/images/postgresql_icon.png',
'mysql' => 'assets/images/mysql_icon.png',
'redis' => 'assets/images/redis_icon.png',
'mongodb' => 'assets/images/mongodb_icon.png',
_ => null,
};
}

Widget _buildConnectionTile(ConnectionRow conn) {
final isSelected = widget.selectedConnectionId != null &&
widget.selectedConnectionId == conn.id;
Expand All @@ -436,8 +414,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _PostgresConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
onPostgresObjectSelected: widget.onPostgresObjectSelected,
Expand All @@ -449,8 +427,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _MysqlConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
onMysqlObjectSelected: widget.onMysqlObjectSelected,
Expand All @@ -462,8 +440,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _RedisConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
onDatabaseTap: (db) => widget.onRedisDatabaseSelected?.call(conn, db),
Expand All @@ -474,8 +452,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _MongoConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
onDatabaseTap: (db) => widget.onMongoDBDatabaseSelected?.call(conn, db),
Expand All @@ -486,8 +464,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _SqliteConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
onSqliteObjectSelected: widget.onSqliteObjectSelected,
Expand All @@ -499,8 +477,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _ExtensionConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
onObjectSelected: widget.onExtensionObjectSelected,
Expand All @@ -511,8 +489,8 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
return _ConnectionTile(
connection: conn,
isSelected: isSelected,
icon: _iconForType(conn.type),
iconAsset: _iconAssetForType(conn.type),
icon: QueryaIcons.connectionIcon(conn.type),
iconAsset: QueryaIcons.connectionAsset(conn.type),
onRemove: () => _removeConnection(conn.id!),
onTap: () => widget.onConnectionSelected?.call(conn),
);
Expand Down Expand Up @@ -602,7 +580,7 @@ class ConnectionsPanelState extends State<ConnectionsPanel> {
.getFolderIdByName(folderName);
await _createConnection(folderId: folderId);
},
iconForType: _iconForType,
iconForType: QueryaIcons.connectionIcon,
onRemoveConnection: _removeConnection,
onConnectionTap: widget.onConnectionSelected,
onRedisDatabaseTap:
Expand Down
21 changes: 3 additions & 18 deletions lib/features/connections/connections_panel_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -287,29 +287,14 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> {
),
)
else if (_error != null)
material.Padding(
TreeLoadError(
message: _error!,
padding: const material.EdgeInsets.only(
left: 28,
top: 4,
bottom: 8,
),
child: material.Column(
crossAxisAlignment: material.CrossAxisAlignment.start,
children: [
material.SelectableText(
_error!,
style: material.TextStyle(
fontSize: 11,
color: theme.colorScheme.destructive,
),
),
const material.SizedBox(height: 6),
GhostButton(
onPressed: _loadTree,
child: const Text('Retry'),
),
],
),
onRetry: _loadTree,
)
else if (_schema != null)
material.Padding(
Expand Down
Loading
Loading