From a6b4b0fb61a757c6c9dd19b6c553048f4eb38e91 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 18 Oct 2026 17:34:53 +0300 Subject: [PATCH] refactor(connections): read colours through context.colors; a guard keeps the folder off the theme's colorScheme (#1731) --- .../connection_databases_folder.dart | 8 +- .../connections/connections_panel.dart | 81 ++++++++++--------- .../connections_panel_extension.dart | 20 ++--- .../connections/connections_panel_mongo.dart | 44 +++++----- .../connections/connections_panel_mysql.dart | 42 +++++----- .../connections_panel_pg_tree.dart | 44 +++++----- ...connections_panel_postgres_connection.dart | 20 ++--- .../connections/connections_panel_redis.dart | 32 ++++---- .../connections_panel_sidebar.dart | 42 +++++----- .../connections/connections_panel_sqlite.dart | 34 ++++---- lib/features/connections/driver_icon.dart | 3 +- .../connections/environment_section.dart | 2 +- .../querya_connection_tree_row.dart | 22 ++--- .../connections/sdui_tree_builder.dart | 8 +- .../connections/ssh_tunnel_section.dart | 6 +- test/guards/colors_through_context_test.dart | 34 ++++++++ 16 files changed, 238 insertions(+), 204 deletions(-) create mode 100644 test/guards/colors_through_context_test.dart diff --git a/lib/features/connections/connection_databases_folder.dart b/lib/features/connections/connection_databases_folder.dart index 716a0e8f..4b8d7287 100644 --- a/lib/features/connections/connection_databases_folder.dart +++ b/lib/features/connections/connection_databases_folder.dart @@ -57,9 +57,9 @@ class _ConnectionDatabasesFolderState @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); - final primary = theme.colorScheme.primary; - final muted = theme.colorScheme.mutedForeground; + final colors = context.colors; + final primary = colors.primary; + final muted = colors.mutedForeground; final label = 'Databases (${widget.databaseCount})'; final row = material.CallbackShortcuts( @@ -116,7 +116,7 @@ class _ConnectionDatabasesFolderState maxLines: 1, style: material.TextStyle( fontSize: 12, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), ), diff --git a/lib/features/connections/connections_panel.dart b/lib/features/connections/connections_panel.dart index 095190c5..c120603e 100644 --- a/lib/features/connections/connections_panel.dart +++ b/lib/features/connections/connections_panel.dart @@ -83,6 +83,7 @@ import 'package:querya_desktop/core/storage/connection_secrets_store.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/theme/querya_ui_colors.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/ui/querya_tree_indent_guide.dart'; @@ -220,7 +221,7 @@ class TreeObjectFilterBar extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final isFiltered = controller.text.trim().isNotEmpty; return material.Padding( @@ -234,12 +235,12 @@ class TreeObjectFilterBar extends material.StatelessWidget { height: 24, padding: const material.EdgeInsets.symmetric(horizontal: 6), decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.22), + color: colors.muted.withValues(alpha: 0.22), borderRadius: material.BorderRadius.circular(4), border: material.Border.all( color: isFiltered - ? theme.colorScheme.primary.withValues(alpha: 0.5) - : theme.colorScheme.border.withValues(alpha: 0.25), + ? colors.primary.withValues(alpha: 0.5) + : colors.border.withValues(alpha: 0.25), width: 1, ), ), @@ -249,8 +250,8 @@ class TreeObjectFilterBar extends material.StatelessWidget { material.Icons.search_rounded, size: 12, color: isFiltered - ? theme.colorScheme.primary - : theme.colorScheme.mutedForeground, + ? colors.primary + : colors.mutedForeground, ), const Gap(5), material.Expanded( @@ -259,13 +260,13 @@ class TreeObjectFilterBar extends material.StatelessWidget { onChanged: onChanged, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.foreground, + color: colors.foreground, ), decoration: material.InputDecoration( hintText: hintText, hintStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground.withValues(alpha: 0.6), + color: colors.mutedForeground.withValues(alpha: 0.6), ), border: material.InputBorder.none, isDense: true, @@ -279,7 +280,7 @@ class TreeObjectFilterBar extends material.StatelessWidget { style: material.TextStyle( fontSize: 10, fontWeight: material.FontWeight.w600, - color: theme.colorScheme.primary, + color: colors.primary, ), ), const Gap(4), @@ -289,7 +290,7 @@ class TreeObjectFilterBar extends material.StatelessWidget { child: material.Icon( material.Icons.close_rounded, size: 12, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], @@ -763,21 +764,21 @@ class ConnectionsPanelState extends State { /// when the connection is in one, "No folder". Empty when there is nowhere to /// move it. List _moveItems(ConnectionRow conn) { - final theme = Theme.of(context); + final colors = context.colors; final current = conn.folderId; final targets = [ for (final name in _folders) if (_folderIdByName[name] != current) MenuButton( leading: material.Icon(material.Icons.folder_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => _moveConnection(conn, _folderIdByName[name]), child: Text(name), ), if (current != null) MenuButton( leading: material.Icon(material.Icons.folder_off_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => _moveConnection(conn, null), child: const Text('No folder'), ), @@ -786,7 +787,7 @@ class ConnectionsPanelState extends State { return [ MenuButton( leading: material.Icon(material.Icons.drive_file_move_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), subMenu: targets, child: const Text('Move to folder'), ), @@ -907,7 +908,7 @@ class ConnectionsPanelState extends State { final tile = _connectionTileCore(conn); final id = conn.id; if (id == null) return tile; - final theme = Theme.of(context); + final colors = context.colors; return material.Draggable( data: id, maxSimultaneousDrags: 1, @@ -924,19 +925,19 @@ class ConnectionsPanelState extends State { padding: const material.EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: material.BoxDecoration( - color: theme.colorScheme.popover, + color: colors.popover, borderRadius: material.BorderRadius.circular(8), - border: material.Border.all(color: theme.colorScheme.primary), + border: material.Border.all(color: colors.primary), ), child: material.Row( mainAxisSize: material.MainAxisSize.min, children: [ material.Icon(QueryaIcons.connectionIcon(conn.type), - size: 16, color: theme.colorScheme.primary), + size: 16, color: colors.primary), const material.SizedBox(width: 8), material.Text(conn.name, style: material.TextStyle( - fontSize: 13, color: theme.colorScheme.foreground)), + fontSize: 13, color: colors.foreground)), ], ), ), @@ -1092,7 +1093,7 @@ class ConnectionsPanelState extends State { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final q = _searchQuery.trim().toLowerCase(); final filteredConnections = q.isEmpty @@ -1139,10 +1140,10 @@ class ConnectionsPanelState extends State { }, child: material.Container( decoration: material.BoxDecoration( - color: theme.colorScheme.background, + color: colors.background, border: material.Border( right: material.BorderSide( - color: theme.colorScheme.border.withValues(alpha: 0.28), + color: colors.border.withValues(alpha: 0.28), width: 1, ), ), @@ -1168,7 +1169,7 @@ class ConnectionsPanelState extends State { fontSize: 11, letterSpacing: 0.85, fontWeight: material.FontWeight.w600, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -1179,7 +1180,7 @@ class ConnectionsPanelState extends State { vertical: 1, ), decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.28), + color: colors.muted.withValues(alpha: 0.28), borderRadius: material.BorderRadius.circular(8), ), child: material.Text( @@ -1189,7 +1190,7 @@ class ConnectionsPanelState extends State { style: material.TextStyle( fontSize: 10, fontWeight: material.FontWeight.w600, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -1202,12 +1203,12 @@ class ConnectionsPanelState extends State { height: 28, padding: const material.EdgeInsets.symmetric(horizontal: 8), decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.22), + color: colors.muted.withValues(alpha: 0.22), borderRadius: material.BorderRadius.circular(6), border: material.Border.all( color: q.isNotEmpty - ? theme.colorScheme.primary.withValues(alpha: 0.5) - : theme.colorScheme.border.withValues(alpha: 0.25), + ? colors.primary.withValues(alpha: 0.5) + : colors.border.withValues(alpha: 0.25), width: 1, ), ), @@ -1221,8 +1222,8 @@ class ConnectionsPanelState extends State { material.Icons.search_rounded, size: 14, color: value.text.trim().isNotEmpty - ? theme.colorScheme.primary - : theme.colorScheme.mutedForeground, + ? colors.primary + : colors.mutedForeground, ), ), const Gap(6), @@ -1235,13 +1236,13 @@ class ConnectionsPanelState extends State { }), style: material.TextStyle( fontSize: 12, - color: theme.colorScheme.foreground, + color: colors.foreground, ), decoration: material.InputDecoration( hintText: 'Filter connections... (Ctrl+F)', hintStyle: material.TextStyle( fontSize: 12, - color: theme.colorScheme.mutedForeground + color: colors.mutedForeground .withValues(alpha: 0.6), ), border: material.InputBorder.none, @@ -1265,7 +1266,7 @@ class ConnectionsPanelState extends State { child: material.Icon( material.Icons.close_rounded, size: 14, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -1275,7 +1276,7 @@ class ConnectionsPanelState extends State { ), QueryaDivider( height: 1, - color: theme.colorScheme.border.withValues(alpha: 0.22), + color: colors.border.withValues(alpha: 0.22), ), // While a connection from a folder is dragged, a labelled place // to drop it: the empty part of the list works too, but nobody @@ -1292,11 +1293,11 @@ class ConnectionsPanelState extends State { margin: const material.EdgeInsets.fromLTRB(12, 8, 12, 0), padding: const material.EdgeInsets.symmetric(vertical: 10), decoration: material.BoxDecoration( - color: theme.colorScheme.primary.withValues( + color: colors.primary.withValues( alpha: candidates.isEmpty ? 0.06 : 0.18), borderRadius: material.BorderRadius.circular(8), border: material.Border.all( - color: theme.colorScheme.primary + color: colors.primary .withValues(alpha: candidates.isEmpty ? 0.4 : 1), width: 1.5, ), @@ -1306,7 +1307,7 @@ class ConnectionsPanelState extends State { 'Drop here to take it out of the folder', style: material.TextStyle( fontSize: 12, - color: theme.colorScheme.primary, + color: colors.primary, ), ), ), @@ -1389,13 +1390,13 @@ class ConnectionsPanelState extends State { MenuButton( leading: material.Icon(material.Icons.add_rounded, size: 18, - color: theme.colorScheme.mutedForeground), + color: colors.mutedForeground), subMenu: [ MenuButton( leading: material.Icon( material.Icons.settings_ethernet_rounded, size: 18, - color: theme.colorScheme.mutedForeground), + color: colors.mutedForeground), onPressed: (menuContext) async { await Future.delayed( const Duration(milliseconds: 100)); @@ -1408,7 +1409,7 @@ class ConnectionsPanelState extends State { leading: material.Icon( material.Icons.folder_rounded, size: 18, - color: theme.colorScheme.mutedForeground), + color: colors.mutedForeground), onPressed: (menuContext) => _createFolder(menuContext), child: const Text('New Folder'), diff --git a/lib/features/connections/connections_panel_extension.dart b/lib/features/connections/connections_panel_extension.dart index 6c10711b..864bf134 100644 --- a/lib/features/connections/connections_panel_extension.dart +++ b/lib/features/connections/connections_panel_extension.dart @@ -150,7 +150,7 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final material.Widget iconWidget; if (_iconFilePath != null) { iconWidget = DriverIconImage( @@ -169,14 +169,14 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { errorBuilder: (_, __, ___) => material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ); } else { iconWidget = material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ); } @@ -184,7 +184,7 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { items: [ MenuButton( leading: material.Icon(material.Icons.refresh_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) { setState(() => _schema = null); _loadTree(); @@ -193,18 +193,18 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { ), MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onEdit(), child: const Text('Edit connection…'), ), ...widget.moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => widget.onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -235,7 +235,7 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -268,7 +268,7 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if (widget.connection.host != null) @@ -278,7 +278,7 @@ class _ExtensionConnectionTileState extends State<_ExtensionConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], diff --git a/lib/features/connections/connections_panel_mongo.dart b/lib/features/connections/connections_panel_mongo.dart index 18ed1acc..8b7c11b2 100644 --- a/lib/features/connections/connections_panel_mongo.dart +++ b/lib/features/connections/connections_panel_mongo.dart @@ -134,7 +134,7 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final iconWidget = widget.iconAsset != null ? material.Image.asset( widget.iconAsset!, @@ -146,24 +146,24 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> { errorBuilder: (_, __, ___) => material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ) : material.Icon(widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary); + color: colors.primary); return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.add_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => _createDatabase(), child: const Text('Create database'), ), MenuButton( leading: material.Icon(material.Icons.refresh_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) { _databases = []; _loadDatabases(); @@ -172,18 +172,18 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> { ), MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onEdit(), child: const Text('Edit connection…'), ), ...widget.moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => widget.onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -216,7 +216,7 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -248,7 +248,7 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if (widget.connection.host != null) @@ -258,7 +258,7 @@ class _MongoConnectionTileState extends State<_MongoConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], @@ -467,7 +467,7 @@ class _MongoDatabaseNodeState extends State<_MongoDatabaseNode> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final query = _filter.trim().toLowerCase(); final matching = query.isEmpty ? _collections @@ -502,17 +502,17 @@ class _MongoDatabaseNodeState extends State<_MongoDatabaseNode> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), ), icon: QueryaIcons.database, iconSize: QueryaIconSizes.treeConnection, - iconColor: theme.colorScheme.primary.withValues(alpha: 0.7), + iconColor: colors.primary.withValues(alpha: 0.7), textStyle: material.TextStyle( fontSize: 12, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 3, expanded: _expanded, @@ -641,7 +641,7 @@ class _MongoCollectionNode extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return _ConnectionsTreeSelectionBuilder( select: (sel) => sel.selectedConnectionId == connection.id && @@ -654,7 +654,7 @@ class _MongoCollectionNode extends StatelessWidget { leading: material.Icon( material.Icons.description_outlined, size: 18, - color: theme.colorScheme.primary, + color: colors.primary, ), onPressed: (_) => onTap(), child: const Text('Open collection'), @@ -663,7 +663,7 @@ class _MongoCollectionNode extends StatelessWidget { leading: material.Icon( material.Icons.copy_rounded, size: 18, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), onPressed: (_) { Clipboard.setData(ClipboardData(text: name)); @@ -675,7 +675,7 @@ class _MongoCollectionNode extends StatelessWidget { leading: material.Icon( material.Icons.refresh_rounded, size: 18, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), onPressed: (_) => onRefreshCollections(), child: const Text('Refresh'), @@ -684,7 +684,7 @@ class _MongoCollectionNode extends StatelessWidget { leading: material.Icon( material.Icons.delete_outline_rounded, size: 18, - color: theme.colorScheme.destructive, + color: colors.destructive, ), onPressed: (_) => onDropCollection(name), child: const Text('Drop collection'), @@ -695,10 +695,10 @@ class _MongoCollectionNode extends StatelessWidget { isSelected: isSelected, icon: material.Icons.table_chart_outlined, iconSize: QueryaIconSizes.treeLeaf, - iconColor: QueryaTreeTokens.leafIconColor(theme.colorScheme.primary), + iconColor: QueryaTreeTokens.leafIconColor(colors.primary), textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 2, onTap: onTap, diff --git a/lib/features/connections/connections_panel_mysql.dart b/lib/features/connections/connections_panel_mysql.dart index f073653e..2ac4c507 100644 --- a/lib/features/connections/connections_panel_mysql.dart +++ b/lib/features/connections/connections_panel_mysql.dart @@ -109,7 +109,7 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final iconWidget = widget.iconAsset != null ? material.Image.asset( widget.iconAsset!, @@ -121,18 +121,18 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> { errorBuilder: (_, __, ___) => material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ) : material.Icon(widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary); + color: colors.primary); return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.refresh_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) { _databases = []; _loadDatabases(); @@ -142,25 +142,25 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> { if (widget.onMysqlOpenSqlWorkspace != null) MenuButton( leading: material.Icon(material.Icons.terminal_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onMysqlOpenSqlWorkspace!(widget.connection), child: const Text('Open in SQL'), ), MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onEdit(), child: const Text('Edit connection…'), ), ...widget.moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => widget.onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -191,7 +191,7 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -222,7 +222,7 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if (widget.connection.host != null) @@ -232,7 +232,7 @@ class _MysqlConnectionTileState extends State<_MysqlConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], @@ -438,7 +438,7 @@ class _MysqlDatabaseNodeState extends State<_MysqlDatabaseNode> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return QueryaTreeIndentGuide( depth: 1, child: material.Column( @@ -454,15 +454,15 @@ class _MysqlDatabaseNodeState extends State<_MysqlDatabaseNode> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: QueryaIcons.database, iconSize: QueryaIconSizes.treeConnection, - iconColor: theme.colorScheme.primary.withValues(alpha: 0.7), + iconColor: colors.primary.withValues(alpha: 0.7), textStyle: material.TextStyle( fontSize: 12, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 4, expanded: _expanded, @@ -634,7 +634,7 @@ class _MysqlObjectGroupState extends State<_MysqlObjectGroup> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final query = _filter.trim().toLowerCase(); final matching = query.isEmpty ? widget.items @@ -663,15 +663,15 @@ class _MysqlObjectGroupState extends State<_MysqlObjectGroup> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: widget.icon, iconSize: QueryaIconSizes.treeGroup, - iconColor: theme.colorScheme.mutedForeground, + iconColor: colors.mutedForeground, textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), expanded: _expanded, onTap: () => setState(() => _expanded = !_expanded), @@ -748,11 +748,11 @@ class _MysqlObjectGroupState extends State<_MysqlObjectGroup> { icon: widget.itemIcon, iconSize: QueryaIconSizes.treeLeaf, iconColor: QueryaTreeTokens.leafIconColor( - theme.colorScheme.primary, + colors.primary, ), textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 2, onTap: widget.onItemTap != null diff --git a/lib/features/connections/connections_panel_pg_tree.dart b/lib/features/connections/connections_panel_pg_tree.dart index 8fb15a07..1a2a30f9 100644 --- a/lib/features/connections/connections_panel_pg_tree.dart +++ b/lib/features/connections/connections_panel_pg_tree.dart @@ -119,7 +119,7 @@ class _PgDatabaseNodeState extends State<_PgDatabaseNode> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return QueryaTreeIndentGuide( depth: 1, child: material.Column( @@ -135,15 +135,15 @@ class _PgDatabaseNodeState extends State<_PgDatabaseNode> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: QueryaIcons.database, iconSize: QueryaIconSizes.treeConnection, - iconColor: theme.colorScheme.primary.withValues(alpha: 0.7), + iconColor: colors.primary.withValues(alpha: 0.7), textStyle: material.TextStyle( fontSize: 12, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 4, expanded: _expanded, @@ -234,8 +234,8 @@ class _PgDbToolRow extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); - final muted = theme.colorScheme.mutedForeground; + final colors = context.colors; + final muted = colors.mutedForeground; return QueryaTreeIndentGuide( depth: 1, padding: const material.EdgeInsets.only(top: 2, bottom: 2), @@ -302,7 +302,7 @@ class _PgSchemasNodeState extends State<_PgSchemasNode> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return QueryaTreeIndentGuide( depth: 1, child: material.Column( @@ -318,15 +318,15 @@ class _PgSchemasNodeState extends State<_PgSchemasNode> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: QueryaIcons.schemasFolder, iconSize: QueryaIconSizes.treeGroup, - iconColor: theme.colorScheme.mutedForeground, + iconColor: colors.mutedForeground, textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), expanded: _expanded, onTap: () => setState(() => _expanded = !_expanded), @@ -490,7 +490,7 @@ class _PgSchemaNodeState extends State<_PgSchemaNode> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return QueryaTreeIndentGuide( depth: 1, child: material.Column( @@ -506,15 +506,15 @@ class _PgSchemaNodeState extends State<_PgSchemaNode> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: QueryaIcons.schema, iconSize: QueryaIconSizes.treeGroup, - iconColor: theme.colorScheme.primary.withValues(alpha: 0.6), + iconColor: colors.primary.withValues(alpha: 0.6), textStyle: material.TextStyle( fontSize: 12, - color: theme.colorScheme.foreground, + color: colors.foreground, ), expanded: _expanded, onTap: _toggle, @@ -724,8 +724,8 @@ class _PgSchemaToolRow extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); - final muted = theme.colorScheme.mutedForeground; + final colors = context.colors; + final muted = colors.mutedForeground; return QueryaTreeIndentGuide( depth: 1, padding: const material.EdgeInsets.only(top: 2, bottom: 2), @@ -807,7 +807,7 @@ class _PgObjectGroupState extends State<_PgObjectGroup> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final query = _filter.trim().toLowerCase(); final matching = query.isEmpty ? widget.items @@ -836,15 +836,15 @@ class _PgObjectGroupState extends State<_PgObjectGroup> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: widget.icon, iconSize: QueryaIconSizes.treeGroup, - iconColor: theme.colorScheme.mutedForeground, + iconColor: colors.mutedForeground, textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), expanded: _expanded, onTap: () => setState(() => _expanded = !_expanded), @@ -925,11 +925,11 @@ class _PgObjectGroupState extends State<_PgObjectGroup> { icon: widget.itemIcon, iconSize: QueryaIconSizes.treeLeaf, iconColor: QueryaTreeTokens.leafIconColor( - theme.colorScheme.primary, + colors.primary, ), textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 2, onTap: widget.onItemTap != null diff --git a/lib/features/connections/connections_panel_postgres_connection.dart b/lib/features/connections/connections_panel_postgres_connection.dart index 0e8cd8e6..8eec17e6 100644 --- a/lib/features/connections/connections_panel_postgres_connection.dart +++ b/lib/features/connections/connections_panel_postgres_connection.dart @@ -112,7 +112,7 @@ class _PostgresConnectionTileState extends State<_PostgresConnectionTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final iconWidget = widget.iconAsset != null ? material.Image.asset( widget.iconAsset!, @@ -124,18 +124,18 @@ class _PostgresConnectionTileState extends State<_PostgresConnectionTile> { errorBuilder: (_, __, ___) => material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ) : material.Icon(widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary); + color: colors.primary); return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.refresh_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) { _databases = []; _loadDatabases(); @@ -144,18 +144,18 @@ class _PostgresConnectionTileState extends State<_PostgresConnectionTile> { ), MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onEdit(), child: const Text('Edit connection…'), ), ...widget.moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => widget.onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -186,7 +186,7 @@ class _PostgresConnectionTileState extends State<_PostgresConnectionTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -217,7 +217,7 @@ class _PostgresConnectionTileState extends State<_PostgresConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if (widget.connection.host != null) @@ -227,7 +227,7 @@ class _PostgresConnectionTileState extends State<_PostgresConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], diff --git a/lib/features/connections/connections_panel_redis.dart b/lib/features/connections/connections_panel_redis.dart index 06ef3e8c..46c44bd6 100644 --- a/lib/features/connections/connections_panel_redis.dart +++ b/lib/features/connections/connections_panel_redis.dart @@ -122,7 +122,7 @@ class _RedisConnectionTileState extends State<_RedisConnectionTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final iconWidget = widget.iconAsset != null ? material.Image.asset( widget.iconAsset!, @@ -134,18 +134,18 @@ class _RedisConnectionTileState extends State<_RedisConnectionTile> { errorBuilder: (_, __, ___) => material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ) : material.Icon(widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary); + color: colors.primary); return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.refresh_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) { _databases = []; _loadDatabases(); @@ -154,18 +154,18 @@ class _RedisConnectionTileState extends State<_RedisConnectionTile> { ), MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onEdit(), child: const Text('Edit connection…'), ), ...widget.moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => widget.onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -198,7 +198,7 @@ class _RedisConnectionTileState extends State<_RedisConnectionTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -230,7 +230,7 @@ class _RedisConnectionTileState extends State<_RedisConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if (widget.connection.host != null) @@ -240,7 +240,7 @@ class _RedisConnectionTileState extends State<_RedisConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], @@ -344,7 +344,7 @@ class _RedisDatabaseNode extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return _ConnectionsTreeSelectionBuilder( select: (sel) => sel.selectedConnectionId == connection.id && @@ -358,22 +358,22 @@ class _RedisDatabaseNode extends StatelessWidget { icon: QueryaIcons.database, iconSize: QueryaIconSizes.treeConnection, iconColor: keys > 0 - ? theme.colorScheme.primary.withValues(alpha: 0.7) - : theme.colorScheme.mutedForeground.withValues(alpha: 0.5), + ? colors.primary.withValues(alpha: 0.7) + : colors.mutedForeground.withValues(alpha: 0.5), trailing: keys > 0 ? material.Text( '$keys', style: material.TextStyle( fontSize: 10, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ) : null, textStyle: material.TextStyle( fontSize: 12, color: keys > 0 - ? theme.colorScheme.foreground - : theme.colorScheme.mutedForeground, + ? colors.foreground + : colors.mutedForeground, ), verticalPadding: 3, onTap: onTap, diff --git a/lib/features/connections/connections_panel_sidebar.dart b/lib/features/connections/connections_panel_sidebar.dart index 48dac237..130134ad 100644 --- a/lib/features/connections/connections_panel_sidebar.dart +++ b/lib/features/connections/connections_panel_sidebar.dart @@ -36,15 +36,15 @@ class _EmptyState extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; return material.Container( padding: const material.EdgeInsets.symmetric(horizontal: 12, vertical: 14), decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.25), + color: colors.muted.withValues(alpha: 0.25), borderRadius: material.BorderRadius.circular(8), border: material.Border.all( - color: theme.colorScheme.border.withValues(alpha: 0.2), + color: colors.border.withValues(alpha: 0.2), width: 1, ), ), @@ -54,7 +54,7 @@ class _EmptyState extends StatelessWidget { material.Icon( material.Icons.info_outline_rounded, size: 16, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), const Gap(10), material.Expanded( @@ -93,7 +93,7 @@ class _ConnectionTile extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final iconWidget = iconAsset != null ? material.Image.asset( iconAsset!, @@ -105,30 +105,30 @@ class _ConnectionTile extends StatelessWidget { errorBuilder: (_, __, ___) => material.Icon( icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ) : material.Icon( icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ); return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => onEdit(), child: const Text('Edit connection…'), ), ...moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -156,7 +156,7 @@ class _ConnectionTile extends StatelessWidget { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if (connection.host != null) @@ -166,7 +166,7 @@ class _ConnectionTile extends StatelessWidget { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], @@ -249,9 +249,9 @@ class _FolderTileState extends State<_FolderTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final drop = widget.onDrop; - final menu = _buildMenu(context, theme); + final menu = _buildMenu(context, colors); if (drop == null) return menu; return material.DragTarget( onWillAcceptWithDetails: (d) => widget.acceptsDrop?.call(d.data) ?? true, @@ -264,7 +264,7 @@ class _FolderTileState extends State<_FolderTile> { border: material.Border.all( color: candidates.isEmpty ? material.Colors.transparent - : theme.colorScheme.primary, + : colors.primary, width: 1.5, ), ), @@ -273,18 +273,18 @@ class _FolderTileState extends State<_FolderTile> { ); } - Widget _buildMenu(BuildContext context, ThemeData theme) { + Widget _buildMenu(BuildContext context, QueryaUiColors colors) { return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.settings_ethernet_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (menuContext) => widget.onNewConnection(widget.name), child: const Text('New connection'), ), MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onRemove(), child: const Text('Remove folder'), ), @@ -317,13 +317,13 @@ class _FolderTileState extends State<_FolderTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), const Gap(2), material.Icon(QueryaIcons.folder, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary), + color: colors.primary), const Gap(8), material.Expanded( child: material.Text( @@ -332,7 +332,7 @@ class _FolderTileState extends State<_FolderTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), ), diff --git a/lib/features/connections/connections_panel_sqlite.dart b/lib/features/connections/connections_panel_sqlite.dart index 2fbde8b8..6dfa4201 100644 --- a/lib/features/connections/connections_panel_sqlite.dart +++ b/lib/features/connections/connections_panel_sqlite.dart @@ -132,7 +132,7 @@ class _SqliteConnectionTileState extends State<_SqliteConnectionTile> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final iconWidget = widget.iconAsset != null ? material.Image.asset( widget.iconAsset!, @@ -144,18 +144,18 @@ class _SqliteConnectionTileState extends State<_SqliteConnectionTile> { errorBuilder: (_, __, ___) => material.Icon( widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary, + color: colors.primary, ), ) : material.Icon(widget.icon, size: QueryaIconSizes.sidebarConnectionIcon, - color: theme.colorScheme.primary); + color: colors.primary); return ContextMenu( items: [ MenuButton( leading: material.Icon(material.Icons.refresh_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) { setState(() { _tables = []; @@ -168,25 +168,25 @@ class _SqliteConnectionTileState extends State<_SqliteConnectionTile> { if (widget.onSqliteOpenSqlWorkspace != null) MenuButton( leading: material.Icon(material.Icons.terminal_rounded, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onSqliteOpenSqlWorkspace!(widget.connection), child: const Text('Open in SQL'), ), MenuButton( leading: material.Icon(material.Icons.edit_outlined, - size: 18, color: theme.colorScheme.mutedForeground), + size: 18, color: colors.mutedForeground), onPressed: (_) => widget.onEdit(), child: const Text('Edit connection…'), ), ...widget.moveItems, MenuButton( leading: material.Icon(material.Icons.delete_outline_rounded, - size: 18, color: theme.colorScheme.destructive), + size: 18, color: colors.destructive), onPressed: (_) => widget.onRemove(), child: Text( 'Remove connection', - style: material.TextStyle(color: theme.colorScheme.destructive), + style: material.TextStyle(color: colors.destructive), ), ), ], @@ -217,7 +217,7 @@ class _SqliteConnectionTileState extends State<_SqliteConnectionTile> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.sidebarExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ), @@ -248,7 +248,7 @@ class _SqliteConnectionTileState extends State<_SqliteConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 13, - color: theme.colorScheme.foreground, + color: colors.foreground, ), ), if ((widget.connection.host ?? @@ -261,7 +261,7 @@ class _SqliteConnectionTileState extends State<_SqliteConnectionTile> { maxLines: 1, style: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), ], @@ -398,7 +398,7 @@ class _SqliteObjectGroupState extends State<_SqliteObjectGroup> { @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final colors = context.colors; final query = _filter.trim().toLowerCase(); final matching = query.isEmpty ? widget.items @@ -427,15 +427,15 @@ class _SqliteObjectGroupState extends State<_SqliteObjectGroup> { child: material.Icon( QueryaIcons.expandClosed, size: QueryaIconSizes.treeExpand, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), ), icon: widget.icon, iconSize: QueryaIconSizes.treeGroup, - iconColor: theme.colorScheme.mutedForeground, + iconColor: colors.mutedForeground, textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), expanded: _expanded, onTap: () => setState(() => _expanded = !_expanded), @@ -510,11 +510,11 @@ class _SqliteObjectGroupState extends State<_SqliteObjectGroup> { icon: widget.itemIcon, iconSize: QueryaIconSizes.treeLeaf, iconColor: QueryaTreeTokens.leafIconColor( - theme.colorScheme.primary, + colors.primary, ), textStyle: material.TextStyle( fontSize: 11, - color: theme.colorScheme.foreground, + color: colors.foreground, ), verticalPadding: 2, onTap: widget.onItemTap != null diff --git a/lib/features/connections/driver_icon.dart b/lib/features/connections/driver_icon.dart index 4628fea8..aa0459cc 100644 --- a/lib/features/connections/driver_icon.dart +++ b/lib/features/connections/driver_icon.dart @@ -67,11 +67,10 @@ class DriverIconImage extends StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = context.theme; final fallback = material.Icon( fallbackIcon, size: size, - color: theme.colorScheme.primary, + color: context.colors.primary, ); final file = File(path); diff --git a/lib/features/connections/environment_section.dart b/lib/features/connections/environment_section.dart index f11ee075..c9781d19 100644 --- a/lib/features/connections/environment_section.dart +++ b/lib/features/connections/environment_section.dart @@ -17,7 +17,7 @@ class EnvironmentSection extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final muted = Theme.of(context).colorScheme.mutedForeground; + final muted = context.colors.mutedForeground; return material.Column( crossAxisAlignment: material.CrossAxisAlignment.stretch, children: [ diff --git a/lib/features/connections/querya_connection_tree_row.dart b/lib/features/connections/querya_connection_tree_row.dart index 66195fd6..50f1e9dd 100644 --- a/lib/features/connections/querya_connection_tree_row.dart +++ b/lib/features/connections/querya_connection_tree_row.dart @@ -103,9 +103,9 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); - final primary = theme.colorScheme.primary; - final muted = theme.colorScheme.mutedForeground; + final colors = context.colors; + final primary = colors.primary; + final muted = colors.mutedForeground; final wb = context.workbench; final row = material.CallbackShortcuts( bindings: { @@ -168,7 +168,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { textStyle: isSelected ? textStyle.copyWith( fontWeight: material.FontWeight.w600, - color: theme.colorScheme.foreground, + color: colors.foreground, ) : textStyle, ), @@ -207,7 +207,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { size: 18, color: isPinned ? wb.warning - : theme.colorScheme.mutedForeground, + : colors.mutedForeground, ), onPressed: (_) => onTogglePin!(), child: Text(isPinned ? 'Unpin from top' : 'Pin to top ⭐'), @@ -218,7 +218,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { leading: material.Icon( material.Icons.table_rows_outlined, size: 18, - color: theme.colorScheme.primary, + color: colors.primary, ), onPressed: (_) { final qualified = openSqlSchema != null && openSqlSchema!.isNotEmpty @@ -243,7 +243,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { leading: material.Icon( material.Icons.code_rounded, size: 18, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), onPressed: (_) { final qualified = openSqlSchema != null && openSqlSchema!.isNotEmpty @@ -260,7 +260,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { leading: material.Icon( material.Icons.refresh_rounded, size: 18, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), onPressed: (_) => onContextRefresh!(), child: const Text('Refresh'), @@ -269,7 +269,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { leading: material.Icon( material.Icons.copy_rounded, size: 18, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), onPressed: (_) { Clipboard.setData(ClipboardData(text: label)); @@ -283,7 +283,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { leading: material.Icon( material.Icons.terminal_rounded, size: 18, - color: theme.colorScheme.mutedForeground, + color: colors.mutedForeground, ), onPressed: (_) => onOpenSqlWorkspace!( connection!, @@ -300,7 +300,7 @@ class QueryaConnectionTreeRow extends material.StatelessWidget { leading: material.Icon( material.Icons.delete_outline_rounded, size: 18, - color: theme.colorScheme.destructive, + color: colors.destructive, ), onPressed: (_) => onContextDelete!(), child: Text(contextDeleteLabel ?? 'Delete'), diff --git a/lib/features/connections/sdui_tree_builder.dart b/lib/features/connections/sdui_tree_builder.dart index ec4d346c..84872c86 100644 --- a/lib/features/connections/sdui_tree_builder.dart +++ b/lib/features/connections/sdui_tree_builder.dart @@ -229,9 +229,9 @@ class SduiTreeBuilderState extends material.State { } material.Widget _buildNodeRow(SduiTreeNode node, {required int depth}) { - final theme = Theme.of(context); - final primary = theme.colorScheme.primary; - final muted = theme.colorScheme.mutedForeground; + final colors = context.colors; + final primary = colors.primary; + final muted = colors.mutedForeground; final canExpand = node.expandable || node.hasChildren; final isExpanded = _expanded.contains(node.id); final isLoading = _loading.contains(node.id); @@ -284,7 +284,7 @@ class SduiTreeBuilderState extends material.State { iconColor: iconColor, textStyle: material.TextStyle( fontSize: 11, - color: isBrowsable ? theme.colorScheme.foreground : muted, + color: isBrowsable ? colors.foreground : muted, ), verticalPadding: 3, expanded: canExpand ? isExpanded : null, diff --git a/lib/features/connections/ssh_tunnel_section.dart b/lib/features/connections/ssh_tunnel_section.dart index bbdc4755..915dae2a 100644 --- a/lib/features/connections/ssh_tunnel_section.dart +++ b/lib/features/connections/ssh_tunnel_section.dart @@ -194,8 +194,8 @@ class _SshTunnelSectionState extends material.State { @override material.Widget build(material.BuildContext context) { - final theme = Theme.of(context); - final cs = theme.colorScheme; + final colors = context.colors; + final cs = colors; final wb = context.workbench; return material.Container( @@ -519,7 +519,7 @@ class _AuthTypeChip extends material.StatelessWidget { @override material.Widget build(material.BuildContext context) { - final cs = Theme.of(context).colorScheme; + final cs = context.colors; return material.InkWell( onTap: onTap, diff --git a/test/guards/colors_through_context_test.dart b/test/guards/colors_through_context_test.dart new file mode 100644 index 00000000..bb85ff6d --- /dev/null +++ b/test/guards/colors_through_context_test.dart @@ -0,0 +1,34 @@ +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; + +/// Epic #1465, #1731: colours are read through `context.colors` +/// (`QueryaUiColors`), not through a theme's `colorScheme`. A folder joins +/// [migrated] in the PR that moves it; at the end the list is all of `lib/`. +void main() { + const migrated = [ + 'lib/features/connections', + ]; + + final banned = RegExp(r'\bcolorScheme\b|\bTheme\.of\(|\bColorScheme\b'); + + test('migrated folders read colours through context.colors', () { + final offenders = []; + for (final dir in migrated) { + for (final e in Directory(dir).listSync(recursive: true)) { + if (e is! File || !e.path.endsWith('.dart')) continue; + final lines = e.readAsLinesSync(); + for (var i = 0; i < lines.length; i++) { + final line = lines[i]; + if (line.trimLeft().startsWith('//')) continue; + if (banned.hasMatch(line)) { + offenders.add('${e.path.replaceAll(r'\', '/')}:${i + 1}: ' + '${line.trim()}'); + } + } + } + } + expect(offenders, isEmpty, + reason: 'Use context.colors (QueryaUiColors) instead.'); + }); +}