From 54167499fd4981fb01db71fe2e3e8532ff1ba9d5 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 18 Jun 2026 16:02:41 +0300 Subject: [PATCH 1/6] fix(ui): remove redundant LayoutBuilders preventing AnimatedSize crash in SQL workspaces --- lib/core/layout/vertical_split_pane.dart | 59 +++---- lib/features/mysql/mysql_sql_workspace.dart | 140 ++++++++-------- .../postgresql/postgres_sql_workspace.dart | 152 +++++++++--------- lib/features/sqlite/sqlite_sql_workspace.dart | 136 ++++++++-------- 4 files changed, 240 insertions(+), 247 deletions(-) diff --git a/lib/core/layout/vertical_split_pane.dart b/lib/core/layout/vertical_split_pane.dart index 36dc3cb2..6e9412ae 100644 --- a/lib/core/layout/vertical_split_pane.dart +++ b/lib/core/layout/vertical_split_pane.dart @@ -13,7 +13,7 @@ class SplitPanePair extends StatelessWidget { } /// Vertical split whose drag updates [fraction] without rebuilding [top]/[bottom]. -class VerticalSplitPane extends StatelessWidget { +class VerticalSplitPane extends StatefulWidget { const VerticalSplitPane({ super.key, required this.fraction, @@ -31,36 +31,41 @@ class VerticalSplitPane extends StatelessWidget { final double maxFraction; final Key? handleKey; + @override + State createState() => _VerticalSplitPaneState(); +} + +class _VerticalSplitPaneState extends State { + final GlobalKey _columnKey = GlobalKey(); + @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - final totalHeight = constraints.maxHeight; - return ValueListenableBuilder( - valueListenable: fraction, - builder: (context, value, panes) { - final pair = panes! as SplitPanePair; - final topFlex = (value * 100).round().clamp(20, 80).toInt(); - final bottomFlex = 100 - topFlex; - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded(flex: topFlex, child: pair.top), - _VerticalSplitHandle( - key: handleKey, - onDrag: (dy) { - if (totalHeight <= 0) return; - fraction.value = (fraction.value + dy / totalHeight) - .clamp(minFraction, maxFraction); - }, - ), - Expanded(flex: bottomFlex, child: pair.bottom), - ], - ); - }, - child: SplitPanePair(top: top, bottom: bottom), + return ValueListenableBuilder( + valueListenable: widget.fraction, + builder: (context, value, panes) { + final pair = panes! as SplitPanePair; + final topFlex = (value * 100).round().clamp(20, 80).toInt(); + final bottomFlex = 100 - topFlex; + return Column( + key: _columnKey, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded(flex: topFlex, child: pair.top), + _VerticalSplitHandle( + key: widget.handleKey, + onDrag: (dy) { + final box = _columnKey.currentContext?.findRenderObject() as RenderBox?; + final totalHeight = box?.size.height ?? 0; + if (totalHeight <= 0) return; + widget.fraction.value = (widget.fraction.value + dy / totalHeight) + .clamp(widget.minFraction, widget.maxFraction); + }, + ), + Expanded(flex: bottomFlex, child: pair.bottom), + ], ); }, + child: SplitPanePair(top: widget.top, bottom: widget.bottom), ); } } diff --git a/lib/features/mysql/mysql_sql_workspace.dart b/lib/features/mysql/mysql_sql_workspace.dart index 886bcd76..a489e276 100644 --- a/lib/features/mysql/mysql_sql_workspace.dart +++ b/lib/features/mysql/mysql_sql_workspace.dart @@ -235,81 +235,77 @@ class _MysqlSqlWorkspaceState extends material.State { material.Widget build(material.BuildContext context) { final theme = Theme.of(context); - return material.LayoutBuilder( - builder: (context, constraints) { - return material.CallbackShortcuts( - bindings: { - const material.SingleActivator(LogicalKeyboardKey.f5): () { - if (!_running) { - unawaited(_execute()); - } - }, - }, - child: material.Focus( - autofocus: true, - child: VerticalSplitPane( - fraction: _topFraction, - maxFraction: 0.85, - top: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _MysqlSqlToolbar( - onExecute: _running ? null : _execute, - running: _running, - queryTimeoutSeconds: _queryTimeoutSeconds, - onQueryTimeoutChanged: _onStmtTimeoutChanged, - onOpenPreferences: () => showPreferencesDialog(context), - onOpenHistory: widget.connectionRow.id != null && !_running - ? () { - showSqlQueryHistoryDialog( - context: context, - connectionId: widget.connectionRow.id!, - databaseName: widget.connectionRow.databaseName, - sqlController: _sqlController, - ); - } - : null, - ), - const Divider(height: 1), - Expanded( - child: QueryEditorTab( - controller: _sqlController, - fontSize: _editorFontSize, - ), - ), - ], + return material.CallbackShortcuts( + bindings: { + const material.SingleActivator(LogicalKeyboardKey.f5): () { + if (!_running) { + unawaited(_execute()); + } + }, + }, + child: material.Focus( + autofocus: true, + child: VerticalSplitPane( + fraction: _topFraction, + maxFraction: 0.85, + top: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _MysqlSqlToolbar( + onExecute: _running ? null : _execute, + running: _running, + queryTimeoutSeconds: _queryTimeoutSeconds, + onQueryTimeoutChanged: _onStmtTimeoutChanged, + onOpenPreferences: () => showPreferencesDialog(context), + onOpenHistory: widget.connectionRow.id != null && !_running + ? () { + showSqlQueryHistoryDialog( + context: context, + connectionId: widget.connectionRow.id!, + databaseName: widget.connectionRow.databaseName, + sqlController: _sqlController, + ); + } + : null, ), - bottom: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - material.Container( - height: 44, - padding: const material.EdgeInsets.symmetric( - horizontal: 12, - ), - decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.6), - ), - alignment: material.Alignment.centerLeft, - child: const Text('Data Output').semiBold().small(), - ), - const Divider(height: 1), - Expanded( - child: ResultsTab( - columns: _columns, - rows: _rows, - errorMessage: _error, - isLoading: _running, - affectedRows: _affectedRows, - statusLine: _statusLine, - ), - ), - ], + const Divider(height: 1), + Expanded( + child: QueryEditorTab( + controller: _sqlController, + fontSize: _editorFontSize, + ), ), - ), + ], ), - ); - }, + bottom: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + material.Container( + height: 44, + padding: const material.EdgeInsets.symmetric( + horizontal: 12, + ), + decoration: material.BoxDecoration( + color: theme.colorScheme.muted.withValues(alpha: 0.6), + ), + alignment: material.Alignment.centerLeft, + child: const Text('Data Output').semiBold().small(), + ), + const Divider(height: 1), + Expanded( + child: ResultsTab( + columns: _columns, + rows: _rows, + errorMessage: _error, + isLoading: _running, + affectedRows: _affectedRows, + statusLine: _statusLine, + ), + ), + ], + ), + ), + ), ); } } diff --git a/lib/features/postgresql/postgres_sql_workspace.dart b/lib/features/postgresql/postgres_sql_workspace.dart index 532e6ec8..4d78259b 100644 --- a/lib/features/postgresql/postgres_sql_workspace.dart +++ b/lib/features/postgresql/postgres_sql_workspace.dart @@ -375,87 +375,83 @@ class _PostgresSqlWorkspaceState extends material.State { material.Widget build(material.BuildContext context) { final theme = Theme.of(context); - return material.LayoutBuilder( - builder: (context, constraints) { - return material.CallbackShortcuts( - bindings: { - const material.SingleActivator(LogicalKeyboardKey.f5): () { - if (!_running) _execute(); - }, - }, - child: material.Focus( - autofocus: true, - child: VerticalSplitPane( - fraction: _topFraction, - maxFraction: 0.85, - top: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _SqlToolbar( - sessionDatabase: _effectiveSessionDatabase(), - onExecute: _running ? null : _execute, - running: _running, - autocommit: _autocommit, - onAutocommitChanged: (v) => setState(() => _autocommit = v), - queryTimeoutSeconds: _queryTimeoutSeconds, - onQueryTimeoutChanged: _onStmtTimeoutChanged, - onOpenPreferences: () => showPreferencesDialog(context), - onOpenHistory: widget.connectionRow.id != null && !_running - ? () { - showSqlQueryHistoryDialog( - context: context, - connectionId: widget.connectionRow.id!, - databaseName: _effectiveSessionDatabase(), - sqlController: _sqlController, - ); - } - : null, - txOpen: _txOpen, - onBegin: _running ? null : () => _runTxCommand('BEGIN'), - onCommit: _running ? null : () => _runTxCommand('COMMIT'), - onRollback: - _running ? null : () => _runTxCommand('ROLLBACK'), - ), - const Divider(height: 1), - Expanded( - child: QueryEditorTab( - controller: _sqlController, - fontSize: _editorFontSize, - ), - ), - ], + return material.CallbackShortcuts( + bindings: { + const material.SingleActivator(LogicalKeyboardKey.f5): () { + if (!_running) _execute(); + }, + }, + child: material.Focus( + autofocus: true, + child: VerticalSplitPane( + fraction: _topFraction, + maxFraction: 0.85, + top: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _SqlToolbar( + sessionDatabase: _effectiveSessionDatabase(), + onExecute: _running ? null : _execute, + running: _running, + autocommit: _autocommit, + onAutocommitChanged: (v) => setState(() => _autocommit = v), + queryTimeoutSeconds: _queryTimeoutSeconds, + onQueryTimeoutChanged: _onStmtTimeoutChanged, + onOpenPreferences: () => showPreferencesDialog(context), + onOpenHistory: widget.connectionRow.id != null && !_running + ? () { + showSqlQueryHistoryDialog( + context: context, + connectionId: widget.connectionRow.id!, + databaseName: _effectiveSessionDatabase(), + sqlController: _sqlController, + ); + } + : null, + txOpen: _txOpen, + onBegin: _running ? null : () => _runTxCommand('BEGIN'), + onCommit: _running ? null : () => _runTxCommand('COMMIT'), + onRollback: + _running ? null : () => _runTxCommand('ROLLBACK'), ), - bottom: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - material.Container( - height: 44, - padding: const material.EdgeInsets.symmetric( - horizontal: 12, - ), - decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.6), - ), - alignment: material.Alignment.centerLeft, - child: const Text('Data Output').semiBold().small(), - ), - const Divider(height: 1), - Expanded( - child: ResultsTab( - columns: _columns, - rows: _rows, - errorMessage: _error, - isLoading: _running, - affectedRows: _affectedRows, - statusLine: _statusLine, - ), - ), - ], + const Divider(height: 1), + Expanded( + child: QueryEditorTab( + controller: _sqlController, + fontSize: _editorFontSize, + ), ), - ), + ], ), - ); - }, + bottom: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + material.Container( + height: 44, + padding: const material.EdgeInsets.symmetric( + horizontal: 12, + ), + decoration: material.BoxDecoration( + color: theme.colorScheme.muted.withValues(alpha: 0.6), + ), + alignment: material.Alignment.centerLeft, + child: const Text('Data Output').semiBold().small(), + ), + const Divider(height: 1), + Expanded( + child: ResultsTab( + columns: _columns, + rows: _rows, + errorMessage: _error, + isLoading: _running, + affectedRows: _affectedRows, + statusLine: _statusLine, + ), + ), + ], + ), + ), + ), ); } } diff --git a/lib/features/sqlite/sqlite_sql_workspace.dart b/lib/features/sqlite/sqlite_sql_workspace.dart index 565d13db..8fafa5c8 100644 --- a/lib/features/sqlite/sqlite_sql_workspace.dart +++ b/lib/features/sqlite/sqlite_sql_workspace.dart @@ -180,79 +180,75 @@ class _SqliteSqlWorkspaceState extends material.State { material.Widget build(material.BuildContext context) { final theme = Theme.of(context); - return material.LayoutBuilder( - builder: (context, constraints) { - return material.CallbackShortcuts( - bindings: { - const material.SingleActivator(LogicalKeyboardKey.f5): () { - if (!_running) { - unawaited(_execute()); - } - }, - }, - child: material.Focus( - autofocus: true, - child: VerticalSplitPane( - fraction: _topFraction, - maxFraction: 0.85, - top: material.Column( - crossAxisAlignment: material.CrossAxisAlignment.stretch, - children: [ - _SqliteSqlToolbar( - onExecute: _running ? null : _execute, - running: _running, - onOpenPreferences: () => showPreferencesDialog(context), - onOpenHistory: widget.connectionRow.id != null && !_running - ? () { - showSqlQueryHistoryDialog( - context: context, - connectionId: widget.connectionRow.id!, - databaseName: widget.connectionRow.databaseName, - sqlController: _sqlController, - ); - } - : null, - ), - const Divider(height: 1), - material.Expanded( - child: QueryEditorTab( - controller: _sqlController, - fontSize: _editorFontSize, - ), - ), - ], + return material.CallbackShortcuts( + bindings: { + const material.SingleActivator(LogicalKeyboardKey.f5): () { + if (!_running) { + unawaited(_execute()); + } + }, + }, + child: material.Focus( + autofocus: true, + child: VerticalSplitPane( + fraction: _topFraction, + maxFraction: 0.85, + top: material.Column( + crossAxisAlignment: material.CrossAxisAlignment.stretch, + children: [ + _SqliteSqlToolbar( + onExecute: _running ? null : _execute, + running: _running, + onOpenPreferences: () => showPreferencesDialog(context), + onOpenHistory: widget.connectionRow.id != null && !_running + ? () { + showSqlQueryHistoryDialog( + context: context, + connectionId: widget.connectionRow.id!, + databaseName: widget.connectionRow.databaseName, + sqlController: _sqlController, + ); + } + : null, ), - bottom: material.Column( - crossAxisAlignment: material.CrossAxisAlignment.stretch, - children: [ - material.Container( - height: 44, - padding: const material.EdgeInsets.symmetric( - horizontal: 12, - ), - decoration: material.BoxDecoration( - color: theme.colorScheme.muted.withValues(alpha: 0.6), - ), - alignment: material.Alignment.centerLeft, - child: const Text('Data Output').semiBold().small(), - ), - const Divider(height: 1), - material.Expanded( - child: ResultsTab( - columns: _columns, - rows: _rows, - errorMessage: _error, - isLoading: _running, - affectedRows: _affectedRows, - statusLine: _statusLine, - ), - ), - ], + const Divider(height: 1), + material.Expanded( + child: QueryEditorTab( + controller: _sqlController, + fontSize: _editorFontSize, + ), ), - ), + ], ), - ); - }, + bottom: material.Column( + crossAxisAlignment: material.CrossAxisAlignment.stretch, + children: [ + material.Container( + height: 44, + padding: const material.EdgeInsets.symmetric( + horizontal: 12, + ), + decoration: material.BoxDecoration( + color: theme.colorScheme.muted.withValues(alpha: 0.6), + ), + alignment: material.Alignment.centerLeft, + child: const Text('Data Output').semiBold().small(), + ), + const Divider(height: 1), + material.Expanded( + child: ResultsTab( + columns: _columns, + rows: _rows, + errorMessage: _error, + isLoading: _running, + affectedRows: _affectedRows, + statusLine: _statusLine, + ), + ), + ], + ), + ), + ), ); } } From 74b0daf4f7c7b87ad339bbd12cb728c4f6b8bed4 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 18 Jun 2026 16:02:46 +0300 Subject: [PATCH 2/6] fix(lint): resolve flutter analyze warnings for legacy colors and flow control --- .../parser/querya_theme_color_scheme.dart | 4 ++-- lib/features/mongodb/mongo_stats_view.dart | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/core/theme/parser/querya_theme_color_scheme.dart b/lib/core/theme/parser/querya_theme_color_scheme.dart index 543c2cf3..cb9f4636 100644 --- a/lib/core/theme/parser/querya_theme_color_scheme.dart +++ b/lib/core/theme/parser/querya_theme_color_scheme.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use + import 'package:flutter/foundation.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; @@ -64,7 +66,6 @@ ColorScheme colorSchemeFromQueryaThemeColors({ final destructive = pick('destructive', base.destructive); // querya.theme.v1 still maps this key; shadcn marks the ColorScheme field legacy. - // ignore: deprecated_member_use final destructiveForeground = pick('destructiveForeground', base.destructiveForeground); @@ -85,7 +86,6 @@ ColorScheme colorSchemeFromQueryaThemeColors({ accent: pick('accent', base.accent), accentForeground: pick('accentForeground', base.accentForeground), destructive: destructive, - // ignore: deprecated_member_use destructiveForeground: destructiveForeground, border: pick('border', base.border), input: pick('input', base.input), diff --git a/lib/features/mongodb/mongo_stats_view.dart b/lib/features/mongodb/mongo_stats_view.dart index 923638b9..011cbe77 100644 --- a/lib/features/mongodb/mongo_stats_view.dart +++ b/lib/features/mongodb/mongo_stats_view.dart @@ -765,10 +765,12 @@ class _MongoStatsViewState extends material.State { Map _extractServerInfo(Map status) { final result = {}; if (status['host'] != null) result['Host'] = status['host'].toString(); - if (status['version'] != null) + if (status['version'] != null) { result['Version'] = status['version'].toString(); - if (status['process'] != null) + } + if (status['process'] != null) { result['Process'] = status['process'].toString(); + } final uptime = _getInt(status, 'uptime'); if (uptime != null) { result['Uptime'] = '${_formatUptime(uptime)} ($uptime s)'; @@ -791,12 +793,15 @@ class _MongoStatsViewState extends material.State { final result = {}; final repl = status['repl'] as Map?; if (repl != null) { - if (repl['setName'] != null) + if (repl['setName'] != null) { result['Replica set'] = repl['setName'].toString(); - if (repl['ismaster'] != null) + } + if (repl['ismaster'] != null) { result['Is master'] = repl['ismaster'].toString(); - if (repl['secondary'] != null) + } + if (repl['secondary'] != null) { result['Secondary'] = repl['secondary'].toString(); + } } return result; } @@ -819,8 +824,9 @@ class _MongoStatsViewState extends material.State { String _formatBytes(int bytes) { if (bytes < 1024) return '$bytes B'; if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB'; - if (bytes < 1024 * 1024 * 1024) + if (bytes < 1024 * 1024 * 1024) { return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB'; + } return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB'; } } From ea5f65c9cacb8c11df41dafe873e7455f66afc0c Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 18 Jun 2026 16:11:31 +0300 Subject: [PATCH 3/6] fix(ui): use minHeight instead of fixed height for toolbars to support accessibility scaling --- lib/features/main_screen/workspace_panel.dart | 5 +++-- lib/features/mongodb/mongo_documents_view.dart | 2 +- lib/features/mongodb/mongo_explorer_view.dart | 2 +- lib/features/mysql/mysql_sql_workspace.dart | 2 +- lib/features/mysql/mysql_workspace_home.dart | 2 +- lib/features/postgresql/postgres_sql_workspace.dart | 2 +- lib/features/postgresql/postgres_workspace_home.dart | 2 +- lib/features/redis/redis_explorer_view.dart | 2 +- lib/features/redis/redis_keys_view.dart | 2 +- lib/features/sqlite/sqlite_sql_workspace.dart | 2 +- lib/features/sqlite/sqlite_workspace_home.dart | 2 +- 11 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/features/main_screen/workspace_panel.dart b/lib/features/main_screen/workspace_panel.dart index 500abf0e..9e5acd11 100644 --- a/lib/features/main_screen/workspace_panel.dart +++ b/lib/features/main_screen/workspace_panel.dart @@ -19,7 +19,8 @@ import 'package:flutter/material.dart' as material SingleChildScrollView, Row, MainAxisSize, - Widget; + Widget, + BoxConstraints; import 'package:querya_desktop/core/layout/vertical_split_pane.dart'; import 'package:querya_desktop/core/motion/querya_cross_fade_stack.dart'; import 'package:querya_desktop/core/motion/querya_motion.dart'; @@ -307,7 +308,7 @@ class _SectionBar extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); return material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 12), decoration: material.BoxDecoration( color: theme.colorScheme.muted.withValues(alpha: 0.6), diff --git a/lib/features/mongodb/mongo_documents_view.dart b/lib/features/mongodb/mongo_documents_view.dart index 67c44444..b8321f1e 100644 --- a/lib/features/mongodb/mongo_documents_view.dart +++ b/lib/features/mongodb/mongo_documents_view.dart @@ -319,7 +319,7 @@ class _MongoDocumentsViewState extends material.State { final to = (_skip + _limit).clamp(0, _totalCount); return material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 16), decoration: material.BoxDecoration( color: shadcnCs.muted.withValues(alpha: 0.15), diff --git a/lib/features/mongodb/mongo_explorer_view.dart b/lib/features/mongodb/mongo_explorer_view.dart index b14a5422..e38a446a 100644 --- a/lib/features/mongodb/mongo_explorer_view.dart +++ b/lib/features/mongodb/mongo_explorer_view.dart @@ -348,7 +348,7 @@ class _BreadcrumbBar extends StatelessWidget { material.Widget build(material.BuildContext context) { final cs = shadcn.Theme.of(context).colorScheme; return material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 16), decoration: material.BoxDecoration( color: cs.muted.withValues(alpha: 0.3), diff --git a/lib/features/mysql/mysql_sql_workspace.dart b/lib/features/mysql/mysql_sql_workspace.dart index a489e276..23fd3f71 100644 --- a/lib/features/mysql/mysql_sql_workspace.dart +++ b/lib/features/mysql/mysql_sql_workspace.dart @@ -281,7 +281,7 @@ class _MysqlSqlWorkspaceState extends material.State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric( horizontal: 12, ), diff --git a/lib/features/mysql/mysql_workspace_home.dart b/lib/features/mysql/mysql_workspace_home.dart index 7a5860d4..81f9f8ad 100644 --- a/lib/features/mysql/mysql_workspace_home.dart +++ b/lib/features/mysql/mysql_workspace_home.dart @@ -66,7 +66,7 @@ class _MysqlWorkspaceHomeState extends material.State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 12), decoration: material.BoxDecoration( color: theme.colorScheme.muted.withValues(alpha: 0.6), diff --git a/lib/features/postgresql/postgres_sql_workspace.dart b/lib/features/postgresql/postgres_sql_workspace.dart index 4d78259b..3377009f 100644 --- a/lib/features/postgresql/postgres_sql_workspace.dart +++ b/lib/features/postgresql/postgres_sql_workspace.dart @@ -427,7 +427,7 @@ class _PostgresSqlWorkspaceState extends material.State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric( horizontal: 12, ), diff --git a/lib/features/postgresql/postgres_workspace_home.dart b/lib/features/postgresql/postgres_workspace_home.dart index a3fdeb68..e2cea5b7 100644 --- a/lib/features/postgresql/postgres_workspace_home.dart +++ b/lib/features/postgresql/postgres_workspace_home.dart @@ -112,7 +112,7 @@ class _PostgresWorkspaceHomeState crossAxisAlignment: material.CrossAxisAlignment.stretch, children: [ material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 12), decoration: material.BoxDecoration( color: theme.colorScheme.muted.withValues(alpha: 0.6), diff --git a/lib/features/redis/redis_explorer_view.dart b/lib/features/redis/redis_explorer_view.dart index fcd3af45..48665b49 100644 --- a/lib/features/redis/redis_explorer_view.dart +++ b/lib/features/redis/redis_explorer_view.dart @@ -277,7 +277,7 @@ class _BreadcrumbBar extends StatelessWidget { material.Widget build(material.BuildContext context) { final cs = shadcn.Theme.of(context).colorScheme; return material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 16), decoration: material.BoxDecoration( color: cs.muted.withValues(alpha: 0.3), diff --git a/lib/features/redis/redis_keys_view.dart b/lib/features/redis/redis_keys_view.dart index 9316b801..99a48f27 100644 --- a/lib/features/redis/redis_keys_view.dart +++ b/lib/features/redis/redis_keys_view.dart @@ -277,7 +277,7 @@ class _RedisKeysViewState extends material.State { Widget _buildStatusBar(ColorScheme cs) { final shadcnCs = shadcn.Theme.of(context).colorScheme; return material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 16), decoration: material.BoxDecoration( color: shadcnCs.muted.withValues(alpha: 0.15), diff --git a/lib/features/sqlite/sqlite_sql_workspace.dart b/lib/features/sqlite/sqlite_sql_workspace.dart index 8fafa5c8..39eba4b2 100644 --- a/lib/features/sqlite/sqlite_sql_workspace.dart +++ b/lib/features/sqlite/sqlite_sql_workspace.dart @@ -224,7 +224,7 @@ class _SqliteSqlWorkspaceState extends material.State { crossAxisAlignment: material.CrossAxisAlignment.stretch, children: [ material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric( horizontal: 12, ), diff --git a/lib/features/sqlite/sqlite_workspace_home.dart b/lib/features/sqlite/sqlite_workspace_home.dart index c49bcadd..654a2656 100644 --- a/lib/features/sqlite/sqlite_workspace_home.dart +++ b/lib/features/sqlite/sqlite_workspace_home.dart @@ -25,7 +25,7 @@ class _SqliteWorkspaceHomeState extends material.State { crossAxisAlignment: material.CrossAxisAlignment.stretch, children: [ material.Container( - height: 44, + constraints: const material.BoxConstraints(minHeight: 44), padding: const material.EdgeInsets.symmetric(horizontal: 12), decoration: material.BoxDecoration( color: theme.colorScheme.muted.withValues(alpha: 0.6), From 147404a82b70f599bedd144ebf808ce7f6498df8 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 18 Jun 2026 16:15:14 +0300 Subject: [PATCH 4/6] fix(ui): scale label width and remove fixed height in preferences to prevent text clipping at 150% scale --- .../settings/preferences_appearance_section.dart | 11 ++++++----- lib/features/settings/preferences_controls.dart | 15 +++++++-------- lib/features/settings/theme_editor_section.dart | 3 ++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/features/settings/preferences_appearance_section.dart b/lib/features/settings/preferences_appearance_section.dart index b2409005..8ec618ce 100644 --- a/lib/features/settings/preferences_appearance_section.dart +++ b/lib/features/settings/preferences_appearance_section.dart @@ -10,6 +10,7 @@ import 'package:querya_desktop/core/theme/theme_import_service.dart'; import 'package:querya_desktop/core/theme/theme_load_result.dart'; import 'package:querya_desktop/core/theme/theme_paths.dart'; import 'package:querya_desktop/features/settings/preferences_controls.dart'; +import 'package:querya_desktop/core/layout/ui_scale.dart'; import 'package:querya_desktop/features/settings/theme_editor_section.dart'; import 'package:querya_desktop/features/settings/theme_picker_button.dart'; import 'package:querya_desktop/features/settings/theme_preview_card.dart'; @@ -206,8 +207,8 @@ class _PreferencesAppearanceSectionState if (c.selectedThemeLoadError != null) ...[ const material.SizedBox(height: 8), material.Padding( - padding: const material.EdgeInsets.only( - left: kPreferencesLabelWidth + 12, + padding: material.EdgeInsets.only( + left: context.scaled(kPreferencesLabelWidth) + 12, ), child: material.Text( c.selectedThemeLoadError!, @@ -219,9 +220,9 @@ class _PreferencesAppearanceSectionState ), ], const material.SizedBox(height: 8), - const material.Padding( - padding: material.EdgeInsets.only(left: kPreferencesLabelWidth + 12), - child: PreferencesHint( + material.Padding( + padding: material.EdgeInsets.only(left: context.scaled(kPreferencesLabelWidth) + 12), + child: const PreferencesHint( 'Themes are loaded from the app support themes folder. ' 'Drop .json or .jsonc files there; the folder is watched automatically ' 'or use Refresh themes.', diff --git a/lib/features/settings/preferences_controls.dart b/lib/features/settings/preferences_controls.dart index 9b03c939..2418fe6e 100644 --- a/lib/features/settings/preferences_controls.dart +++ b/lib/features/settings/preferences_controls.dart @@ -3,6 +3,7 @@ import 'dart:async' show unawaited; import 'package:flutter/material.dart' as material; import 'package:flutter/services.dart'; import 'package:querya_desktop/core/layout/ui_scale_controller.dart'; +import 'package:querya_desktop/core/layout/ui_scale.dart'; import 'package:querya_desktop/core/storage/app_settings.dart'; import 'package:querya_desktop/shared/widgets/querya_dropdown.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; @@ -52,13 +53,11 @@ class PreferencesFieldRow extends StatelessWidget { material.Row( crossAxisAlignment: material.CrossAxisAlignment.start, children: [ - material.SizedBox( - width: labelWidth, - height: triggerHeight, - child: material.Align( - alignment: material.Alignment.centerLeft, - child: Text(label).small().foreground(), - ), + material.Container( + width: context.scaled(labelWidth), + constraints: material.BoxConstraints(minHeight: triggerHeight), + alignment: material.Alignment.centerLeft, + child: Text(label).small().foreground(), ), const material.SizedBox(width: 12), material.Expanded(child: control), @@ -67,7 +66,7 @@ class PreferencesFieldRow extends StatelessWidget { if (hint != null) ...[ const material.SizedBox(height: 4), material.Padding( - padding: material.EdgeInsets.only(left: labelWidth + 12), + padding: material.EdgeInsets.only(left: context.scaled(labelWidth) + 12), child: PreferencesHint(hint!), ), ], diff --git a/lib/features/settings/theme_editor_section.dart b/lib/features/settings/theme_editor_section.dart index 71ca1710..a805411c 100644 --- a/lib/features/settings/theme_editor_section.dart +++ b/lib/features/settings/theme_editor_section.dart @@ -10,6 +10,7 @@ import 'package:querya_desktop/core/theme/theme_editor_draft.dart'; import 'package:querya_desktop/core/theme/theme_editor_loader.dart'; import 'package:querya_desktop/features/settings/preferences_controls.dart'; import 'package:querya_desktop/features/settings/theme_color_picker_dialog.dart'; +import 'package:querya_desktop/core/layout/ui_scale.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; /// MVP visual theme editor in Preferences → Appearance. @@ -240,7 +241,7 @@ class _ThemeEditorColorRow extends material.StatelessWidget { child: material.Row( children: [ material.SizedBox( - width: kPreferencesLabelWidth, + width: context.scaled(kPreferencesLabelWidth), child: material.Text( field.label, style: material.TextStyle( From 8623da7ad002300d4689f1f73f6aa7c2565ac5fa Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 18 Jun 2026 16:18:22 +0300 Subject: [PATCH 5/6] feat(docker): add sqlite test database seeding to docker-compose --- docker/docker-compose.yml | 12 ++++++++++++ docker/sqlite/init.sql | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 docker/sqlite/init.sql diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index fd0ad3d1..508b9fc2 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -14,6 +14,8 @@ # Redis port 6379 no auth keys prefix querya:* # MongoDB port 27017 db querya user querya password querya # auth source: admin collections: users, products, orders +# SQLite local file ./sqlite/data/querya.db +# tables: users, products, orders # ───────────────────────────────────────────────────────────────────────── name: querya-dev @@ -135,6 +137,16 @@ services: retries: 20 start_period: 30s + sqlite-seed: + image: alpine:latest + container_name: querya-sqlite-seed + volumes: + - ./sqlite/data:/data + - ./sqlite/init.sql:/init.sql:ro + command: > + sh -c "apk add --no-cache sqlite && sqlite3 /data/querya.db < /init.sql && chmod 666 /data/querya.db && echo 'SQLite DB seeded'" + restart: "no" + volumes: postgres_data: mysql_data: diff --git a/docker/sqlite/init.sql b/docker/sqlite/init.sql new file mode 100644 index 00000000..172eea4c --- /dev/null +++ b/docker/sqlite/init.sql @@ -0,0 +1,41 @@ +-- Querya SQLite Test Database Initialization +-- This script runs once via Docker to seed the local querya.db file. + +CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + email TEXT NOT NULL UNIQUE, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS products ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + price REAL NOT NULL, + stock INTEGER DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS orders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + total REAL NOT NULL, + status TEXT DEFAULT 'pending', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY(user_id) REFERENCES users(id) +); + +-- Seed Data +INSERT OR IGNORE INTO users (id, username, email) VALUES +(1, 'alice_smith', 'alice@example.com'), +(2, 'bob_jones', 'bob@example.com'), +(3, 'charlie_brown', 'charlie@example.com'); + +INSERT OR IGNORE INTO products (id, name, price, stock) VALUES +(1, 'Laptop Pro', 1299.99, 50), +(2, 'Wireless Mouse', 49.99, 200), +(3, 'Mechanical Keyboard', 149.50, 75); + +INSERT OR IGNORE INTO orders (id, user_id, total, status) VALUES +(1, 1, 1299.99, 'completed'), +(2, 2, 49.99, 'shipped'), +(3, 1, 149.50, 'pending'); From 6cfc8ce019742dccfc313f9a935f2f3b915d3fa0 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 18 Jun 2026 16:19:47 +0300 Subject: [PATCH 6/6] chore: ignore local sqlite docker data directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1960cc1d..dfdc4895 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ coverage/ *.dll *.exe design-front/ +docker/sqlite/data/