From b615373bdf2603fde2ddbb789286c154145af1ae Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 11 Oct 2026 07:52:25 +0300 Subject: [PATCH 1/2] refactor(ui): connection forms and dialogs use QueryaButton Footers of the connection forms, SQL editor dialogs, table privileges, theme dialogs, query history and the recovery app move to QueryaButton at lg (Cancel is ghost). Test Connection is a secondary button with the button's loading state instead of a hand-built spinner leading, and the certificate browse icon is a QueryaButton.icon with a tooltip. Part of #1338. --- .../extension_connection_form.dart | 29 +++++------ .../connections/sqlite_connection_form.dart | 47 +++++++----------- .../connections/ssh_tunnel_section.dart | 30 ++++++------ .../mongodb/mongo_create_index_dialog.dart | 24 +++++----- .../mongodb/mongodb_connection_form.dart | 42 +++++----------- lib/features/mysql/mysql_connection_form.dart | 42 +++++----------- .../mysql/mysql_sql_editor_dialog.dart | 16 ++++--- .../postgres_sql_editor_dialog.dart | 16 ++++--- .../postgres_table_privileges_dialog.dart | 11 +++-- .../postgresql_connection_form.dart | 48 +++++++------------ .../recovery/querya_startup_recovery_app.dart | 21 ++++---- lib/features/redis/redis_connection_form.dart | 42 +++++----------- .../settings/theme_color_picker_dialog.dart | 11 +++-- .../settings/theme_editor_dialog.dart | 18 +++---- .../settings/theme_remote_install_dialog.dart | 11 +++-- .../workspace/sql_query_history_dialog.dart | 41 +++++++++------- 16 files changed, 201 insertions(+), 248 deletions(-) diff --git a/lib/features/connections/extension_connection_form.dart b/lib/features/connections/extension_connection_form.dart index e0479e9d..da776a74 100644 --- a/lib/features/connections/extension_connection_form.dart +++ b/lib/features/connections/extension_connection_form.dart @@ -14,6 +14,7 @@ import 'package:querya_desktop/core/sdui/sdui_form_schema.dart'; import 'package:querya_desktop/core/storage/local_db.dart'; import 'package:querya_desktop/features/connections/connection_edit_secrets.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows an SDUI connection form for an installed extension driver. Future showExtensionConnectionForm( @@ -292,28 +293,24 @@ class _ExtensionConnectionFormContentState ), child: material.Row( children: [ - OutlineButton( - onPressed: - _schema == null || _testing ? null : _testConnection, - leading: _testing - ? const QueryaSpinner( - size: QueryaSpinnerSize.sm, - ) - : const material.Icon( - material.Icons.bolt_rounded, - size: 16, - ), - child: const Text('Test Connection'), + QueryaButton.secondary( + label: 'Test Connection', + icon: material.Icons.bolt_rounded, + loading: _testing, + size: QueryaControlSize.lg, + onPressed: _schema == null || _testing ? null : _testConnection, ), const Spacer(), - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const material.SizedBox(width: 12), - PrimaryButton( + QueryaButton.primary( + label: 'Save', onPressed: _schema == null ? null : _save, - child: const Text('Save'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/connections/sqlite_connection_form.dart b/lib/features/connections/sqlite_connection_form.dart index a6931fc8..7f005abb 100644 --- a/lib/features/connections/sqlite_connection_form.dart +++ b/lib/features/connections/sqlite_connection_form.dart @@ -10,6 +10,7 @@ import 'package:querya_desktop/core/layout/window_layout.dart'; import 'package:querya_desktop/core/storage/local_db.dart'; import 'package:querya_desktop/shared/widgets/form_validity_notifier.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows SQLite connection form dialog. /// Returns ConnectionRow if saved, null if cancelled. @@ -282,9 +283,10 @@ class _SqliteConnectionFormContentState ), ), const Gap(10), - OutlineButton( + QueryaButton.secondary( + label: 'Browse…', onPressed: _pickFile, - child: const Text('Browse…'), + size: QueryaControlSize.lg, ), ], ), @@ -394,44 +396,27 @@ class _SqliteConnectionFormContentState runSpacing: 8, alignment: material.WrapAlignment.spaceBetween, children: [ - OutlineButton( - onPressed: - formValid && !_isTesting ? _testConnection : null, - leading: _isTesting - ? QueryaSpinner( - customDimension: 18, - strokeWidth: 2, - color: theme.primary, - ) - : material.Icon( - material.Icons.link_rounded, - size: 18, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - child: Text( - 'Test Connection', - style: material.TextStyle( - fontWeight: material.FontWeight.w500, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - ), + QueryaButton.secondary( + label: 'Test Connection', + icon: material.Icons.link_rounded, + loading: _isTesting, + size: QueryaControlSize.lg, + onPressed: formValid && !_isTesting ? _testConnection : null, ), material.Row( mainAxisSize: material.MainAxisSize.min, children: [ - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(12), - PrimaryButton( + QueryaButton.primary( + label: 'Save', onPressed: formValid ? _save : null, - child: const Text('Save'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/connections/ssh_tunnel_section.dart b/lib/features/connections/ssh_tunnel_section.dart index 808a1e9e..e94c4527 100644 --- a/lib/features/connections/ssh_tunnel_section.dart +++ b/lib/features/connections/ssh_tunnel_section.dart @@ -4,6 +4,7 @@ import 'package:querya_desktop/core/security/ssh_tunnel_config.dart'; import 'package:querya_desktop/core/security/ssh_tunnel_manager.dart'; import 'package:querya_desktop/features/connections/connection_edit_secrets.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Reusable UI section for configuring SSH Bastion / Jump Host tunneling /// in connection dialogs. @@ -384,9 +385,10 @@ class _SshTunnelSectionState extends material.State { ), ), const Gap(8), - OutlineButton( + QueryaButton.secondary( + label: 'Browse…', onPressed: _pickPrivateKeyFile, - child: const Text('Browse…'), + size: QueryaControlSize.lg, ), ], ), @@ -440,24 +442,20 @@ class _SshTunnelSectionState extends material.State { runSpacing: 8, crossAxisAlignment: material.WrapCrossAlignment.center, children: [ - OutlineButton( - size: ButtonSize.small, + QueryaButton.secondary( + label: 'Test SSH Connection', + icon: material.Icons.network_check_rounded, + loading: _testing, + size: QueryaControlSize.sm, onPressed: _testing ? null : _testSsh, - leading: _testing - ? const QueryaSpinner(size: QueryaSpinnerSize.sm) - : const material.Icon( - material.Icons.network_check_rounded, - size: 15, - ), - child: const Text('Test SSH Connection'), ), - GhostButton( - size: ButtonSize.small, + QueryaButton.ghost( + label: _showAdvanced + ? 'Hide Advanced ▲' + : 'Advanced (Host Key & Keep-Alive) ▼', onPressed: () => setState(() => _showAdvanced = !_showAdvanced), - child: Text(_showAdvanced - ? 'Hide Advanced ▲' - : 'Advanced (Host Key & Keep-Alive) ▼'), + size: QueryaControlSize.sm, ), ], ), diff --git a/lib/features/mongodb/mongo_create_index_dialog.dart b/lib/features/mongodb/mongo_create_index_dialog.dart index f7d60452..72583fc9 100644 --- a/lib/features/mongodb/mongo_create_index_dialog.dart +++ b/lib/features/mongodb/mongo_create_index_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart' as material; import 'package:querya_desktop/core/database/mongodb_connection.dart'; import 'package:querya_desktop/core/database/mongodb_service.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; class _IndexFieldDraft { _IndexFieldDraft({String field = '', dynamic direction = 1}) @@ -279,11 +280,11 @@ class _MongoCreateIndexDialogState ], material.Align( alignment: material.Alignment.centerLeft, - child: GhostButton( + child: QueryaButton.ghost( + label: 'Add Field (Compound)', + icon: material.Icons.add_rounded, onPressed: _addField, - size: ButtonSize.small, - leading: const material.Icon(material.Icons.add_rounded, size: 14), - child: const Text('Add Field (Compound)'), + size: QueryaControlSize.sm, ), ), const Gap(16), @@ -371,16 +372,17 @@ class _MongoCreateIndexDialogState ], ), actions: [ - OutlineButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), - PrimaryButton( + QueryaButton.primary( + label: _submitting ? 'Creating...' : 'Create Index', + icon: material.Icons.check_rounded, + loading: _submitting, + size: QueryaControlSize.lg, onPressed: _submitting ? null : _submit, - leading: _submitting - ? const QueryaSpinner(size: QueryaSpinnerSize.sm) - : const material.Icon(material.Icons.check_rounded, size: 16), - child: Text(_submitting ? 'Creating...' : 'Create Index'), ), ], ); diff --git a/lib/features/mongodb/mongodb_connection_form.dart b/lib/features/mongodb/mongodb_connection_form.dart index 8508e334..ed592cd3 100644 --- a/lib/features/mongodb/mongodb_connection_form.dart +++ b/lib/features/mongodb/mongodb_connection_form.dart @@ -17,6 +17,7 @@ import 'package:querya_desktop/features/connections/ssl_certificate_support.dart import 'package:querya_desktop/shared/widgets/form_validity_notifier.dart'; import 'package:querya_desktop/shared/widgets/ssl_certificate_fields.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// MongoDB connection form data. class MongoConnectionData { @@ -651,41 +652,24 @@ class _MongoConnectionFormContentState builder: (context, formValid, _) { return material.Row( children: [ - OutlineButton( - onPressed: - formValid && !_isTesting ? _testConnection : null, - leading: _isTesting - ? QueryaSpinner( - customDimension: 18, - strokeWidth: 2, - color: theme.primary, - ) - : material.Icon( - material.Icons.link_rounded, - size: 18, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - child: Text( - 'Test Connection', - style: material.TextStyle( - fontWeight: material.FontWeight.w500, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - ), + QueryaButton.secondary( + label: 'Test Connection', + icon: material.Icons.link_rounded, + loading: _isTesting, + size: QueryaControlSize.lg, + onPressed: formValid && !_isTesting ? _testConnection : null, ), const material.Spacer(), - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(12), - PrimaryButton( + QueryaButton.primary( + label: 'Save', onPressed: formValid ? _save : null, - child: const Text('Save'), + size: QueryaControlSize.lg, ), ], ); diff --git a/lib/features/mysql/mysql_connection_form.dart b/lib/features/mysql/mysql_connection_form.dart index 271115da..a0494b1a 100644 --- a/lib/features/mysql/mysql_connection_form.dart +++ b/lib/features/mysql/mysql_connection_form.dart @@ -18,6 +18,7 @@ import 'package:querya_desktop/features/connections/ssl_certificate_support.dart import 'package:querya_desktop/shared/widgets/form_validity_notifier.dart'; import 'package:querya_desktop/shared/widgets/ssl_certificate_fields.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows MySQL / MariaDB connection form dialog. /// Returns [ConnectionRow] if saved, null if cancelled. @@ -559,44 +560,27 @@ class _MysqlConnectionFormContentState runSpacing: 8, alignment: material.WrapAlignment.spaceBetween, children: [ - OutlineButton( - onPressed: - formValid && !_isTesting ? _testConnection : null, - leading: _isTesting - ? QueryaSpinner( - customDimension: 18, - strokeWidth: 2, - color: theme.primary, - ) - : material.Icon( - material.Icons.link_rounded, - size: 18, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - child: Text( - 'Test Connection', - style: material.TextStyle( - fontWeight: material.FontWeight.w500, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - ), + QueryaButton.secondary( + label: 'Test Connection', + icon: material.Icons.link_rounded, + loading: _isTesting, + size: QueryaControlSize.lg, + onPressed: formValid && !_isTesting ? _testConnection : null, ), material.Row( mainAxisSize: material.MainAxisSize.min, children: [ - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(12), - PrimaryButton( + QueryaButton.primary( + label: 'Save', onPressed: formValid ? _save : null, - child: const Text('Save'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/mysql/mysql_sql_editor_dialog.dart b/lib/features/mysql/mysql_sql_editor_dialog.dart index b4f0a9ea..09d03640 100644 --- a/lib/features/mysql/mysql_sql_editor_dialog.dart +++ b/lib/features/mysql/mysql_sql_editor_dialog.dart @@ -5,6 +5,7 @@ import 'package:querya_desktop/core/editor/querya_code_language.dart'; import 'package:querya_desktop/features/workspace/sql_editor_chrome.dart'; import 'package:querya_desktop/features/mysql/mysql_table_utils.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Dialog to view/edit SQL and run it (read-only SELECT for table browse). Future showMysqlSqlEditorDialog({ @@ -137,24 +138,27 @@ class _MysqlSqlEditorDialogState extends material.State<_MysqlSqlEditorDialog> { child: material.Row( mainAxisAlignment: material.MainAxisAlignment.end, children: [ - OutlineButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(8), - OutlineButton( + QueryaButton.secondary( + label: 'Reset', onPressed: () { setState(() { _error = null; _controller.text = widget.browseSql; }); }, - child: const Text('Reset'), + size: QueryaControlSize.lg, ), const Gap(8), - PrimaryButton( + QueryaButton.primary( + label: 'Run', onPressed: _submit, - child: const Text('Run'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/postgresql/postgres_sql_editor_dialog.dart b/lib/features/postgresql/postgres_sql_editor_dialog.dart index aa2f0455..0d961fad 100644 --- a/lib/features/postgresql/postgres_sql_editor_dialog.dart +++ b/lib/features/postgresql/postgres_sql_editor_dialog.dart @@ -5,6 +5,7 @@ import 'package:querya_desktop/core/editor/querya_code_language.dart'; import 'package:querya_desktop/features/postgresql/postgres_table_utils.dart'; import 'package:querya_desktop/features/workspace/sql_editor_chrome.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Dialog to view/edit SQL and run it. /// [initialSql] — text shown when opening; [browseSql] — "Reset" restores table browse query. @@ -139,24 +140,27 @@ class _PostgresSqlEditorDialogState child: material.Row( mainAxisAlignment: material.MainAxisAlignment.end, children: [ - OutlineButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(8), - OutlineButton( + QueryaButton.secondary( + label: 'Reset', onPressed: () { setState(() { _error = null; _controller.text = widget.browseSql; }); }, - child: const Text('Reset'), + size: QueryaControlSize.lg, ), const Gap(8), - PrimaryButton( + QueryaButton.primary( + label: 'Run', onPressed: _submit, - child: const Text('Run'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/postgresql/postgres_table_privileges_dialog.dart b/lib/features/postgresql/postgres_table_privileges_dialog.dart index bb9a707d..a26737a6 100644 --- a/lib/features/postgresql/postgres_table_privileges_dialog.dart +++ b/lib/features/postgresql/postgres_table_privileges_dialog.dart @@ -3,6 +3,7 @@ import 'package:querya_desktop/core/database/postgres_connection.dart'; import 'package:querya_desktop/core/layout/window_layout.dart'; import 'package:querya_desktop/core/database/postgres_metadata.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows [information_schema.role_table_grants] for a table/view/matview. Future showPostgresTablePrivilegesDialog({ @@ -140,15 +141,17 @@ class _PrivilegesDialogBodyState extends material.State<_PrivilegesDialogBody> { child: material.Row( mainAxisAlignment: material.MainAxisAlignment.end, children: [ - OutlineButton( + QueryaButton.ghost( + label: 'Close', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Close'), + size: QueryaControlSize.lg, ), if (!_loading && _error == null) ...[ const Gap(8), - OutlineButton( + QueryaButton.secondary( + label: 'Reload', onPressed: _load, - child: const Text('Reload'), + size: QueryaControlSize.lg, ), ], ], diff --git a/lib/features/postgresql/postgresql_connection_form.dart b/lib/features/postgresql/postgresql_connection_form.dart index 6e1035e3..c9bff6e1 100644 --- a/lib/features/postgresql/postgresql_connection_form.dart +++ b/lib/features/postgresql/postgresql_connection_form.dart @@ -17,6 +17,7 @@ import 'package:querya_desktop/features/connections/forms/connection_database_se import 'package:querya_desktop/features/connections/forms/connection_host_port_section.dart'; import 'package:querya_desktop/shared/widgets/form_validity_notifier.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows PostgreSQL connection form dialog. /// Returns ConnectionRow if saved, null if cancelled. @@ -438,9 +439,11 @@ class _PostgresConnectionFormContentState ), ), const Gap(8), - GhostButton( + QueryaButton.icon( + icon: material.Icons.folder_open_rounded, + tooltip: 'Browse…', + size: QueryaControlSize.lg, onPressed: () => _pickCertificateFile(controller), - child: const Icon(material.Icons.folder_open_rounded), ), ], ), @@ -779,44 +782,27 @@ class _PostgresConnectionFormContentState runSpacing: 8, alignment: material.WrapAlignment.spaceBetween, children: [ - OutlineButton( - onPressed: - formValid && !_isTesting ? _testConnection : null, - leading: _isTesting - ? QueryaSpinner( - customDimension: 18, - strokeWidth: 2, - color: theme.primary, - ) - : material.Icon( - material.Icons.link_rounded, - size: 18, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - child: Text( - 'Test Connection', - style: material.TextStyle( - fontWeight: material.FontWeight.w500, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - ), + QueryaButton.secondary( + label: 'Test Connection', + icon: material.Icons.link_rounded, + loading: _isTesting, + size: QueryaControlSize.lg, + onPressed: formValid && !_isTesting ? _testConnection : null, ), material.Row( mainAxisSize: material.MainAxisSize.min, children: [ - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(12), - PrimaryButton( + QueryaButton.primary( + label: 'Save', onPressed: formValid ? _save : null, - child: const Text('Save'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/recovery/querya_startup_recovery_app.dart b/lib/features/recovery/querya_startup_recovery_app.dart index 2555eada..5b116102 100644 --- a/lib/features/recovery/querya_startup_recovery_app.dart +++ b/lib/features/recovery/querya_startup_recovery_app.dart @@ -7,6 +7,7 @@ import 'package:querya_desktop/core/storage/local_db.dart'; import 'package:querya_desktop/core/theme/theme_controller.dart'; import 'package:querya_desktop/core/ui/querya_icons.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Disaster recovery UI launched when LocalDb fails to open or migrate on startup. /// Allows the user to inspect the error, retry, remove stale locks, backup the database, @@ -215,21 +216,25 @@ class _QueryaStartupRecoveryAppState spacing: 12, runSpacing: 12, children: [ - PrimaryButton( + QueryaButton.primary( + label: 'Retry Opening', onPressed: _isBusy ? null : _handleRetry, - child: const Text('Retry Opening'), + size: QueryaControlSize.lg, ), - OutlineButton( + QueryaButton.secondary( + label: 'Unlock Database (Clear WAL)', onPressed: _isBusy ? null : _handleUnlockWal, - child: const Text('Unlock Database (Clear WAL)'), + size: QueryaControlSize.lg, ), - OutlineButton( + QueryaButton.secondary( + label: 'Export / Backup querya.db', onPressed: _isBusy ? null : _handleBackup, - child: const Text('Export / Backup querya.db'), + size: QueryaControlSize.lg, ), - GhostButton( + QueryaButton.ghost( + label: 'Start in Safe Mode', onPressed: _isBusy ? null : _handleSafeMode, - child: const Text('Start in Safe Mode'), + size: QueryaControlSize.lg, ), ], ), diff --git a/lib/features/redis/redis_connection_form.dart b/lib/features/redis/redis_connection_form.dart index fa82f4d7..c919f4c3 100644 --- a/lib/features/redis/redis_connection_form.dart +++ b/lib/features/redis/redis_connection_form.dart @@ -16,6 +16,7 @@ import 'package:querya_desktop/features/connections/ssl_certificate_support.dart import 'package:querya_desktop/shared/widgets/form_validity_notifier.dart'; import 'package:querya_desktop/shared/widgets/ssl_certificate_fields.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows Redis connection form dialog. Returns ConnectionRow if saved, null if cancelled. Future showRedisConnectionForm( @@ -570,41 +571,24 @@ class _RedisConnectionFormContentState builder: (context, formValid, _) { return material.Row( children: [ - OutlineButton( - onPressed: - formValid && !_isTesting ? _testConnection : null, - leading: _isTesting - ? QueryaSpinner( - customDimension: 18, - strokeWidth: 2, - color: theme.primary, - ) - : material.Icon( - material.Icons.link_rounded, - size: 18, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - child: Text( - 'Test Connection', - style: material.TextStyle( - fontWeight: material.FontWeight.w500, - color: formValid - ? theme.primary - : theme.mutedForeground, - ), - ), + QueryaButton.secondary( + label: 'Test Connection', + icon: material.Icons.link_rounded, + loading: _isTesting, + size: QueryaControlSize.lg, + onPressed: formValid && !_isTesting ? _testConnection : null, ), const material.Spacer(), - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(12), - PrimaryButton( + QueryaButton.primary( + label: 'Save', onPressed: formValid ? _save : null, - child: const Text('Save'), + size: QueryaControlSize.lg, ), ], ); diff --git a/lib/features/settings/theme_color_picker_dialog.dart b/lib/features/settings/theme_color_picker_dialog.dart index baf10f43..553c9d43 100644 --- a/lib/features/settings/theme_color_picker_dialog.dart +++ b/lib/features/settings/theme_color_picker_dialog.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart' as material; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Simple color picker dialog for the theme editor. Future showThemeColorPickerDialog({ @@ -22,14 +23,16 @@ Future showThemeColorPickerDialog({ ), ), actions: [ - OutlineButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.pop(dialogContext), - child: const material.Text('Cancel'), + size: QueryaControlSize.lg, ), - PrimaryButton( + QueryaButton.primary( + label: 'Apply', onPressed: () => material.Navigator.pop(dialogContext, picked.toColor()), - child: const material.Text('Apply'), + size: QueryaControlSize.lg, ), ], ); diff --git a/lib/features/settings/theme_editor_dialog.dart b/lib/features/settings/theme_editor_dialog.dart index 615f809f..f74acc21 100644 --- a/lib/features/settings/theme_editor_dialog.dart +++ b/lib/features/settings/theme_editor_dialog.dart @@ -11,6 +11,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/theme_color_picker_dialog.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows the focused Theme Studio modal dialog with live token editing and real-time preview. Future showThemeEditorDialog(material.BuildContext context) { @@ -254,20 +255,21 @@ class _ThemeEditorDialogState extends material.State { ), ), actions: [ - OutlineButton( + QueryaButton.secondary( + label: 'Reset from current', onPressed: _loading ? null : () => unawaited(_loadDraft()), - child: const material.Text('Reset from current'), + size: QueryaControlSize.lg, ), if (_draft != null) - OutlineButton( + QueryaButton.secondary( + label: _exporting ? 'Exporting…' : 'Export theme…', onPressed: _exporting ? null : () => unawaited(_exportDraft()), - child: material.Text( - _exporting ? 'Exporting…' : 'Export theme…', - ), + size: QueryaControlSize.lg, ), - PrimaryButton( + QueryaButton.primary( + label: 'Done', onPressed: () => material.Navigator.of(context).pop(), - child: const material.Text('Done'), + size: QueryaControlSize.lg, ), ], ); diff --git a/lib/features/settings/theme_remote_install_dialog.dart b/lib/features/settings/theme_remote_install_dialog.dart index 9e3d76ee..c8f7ea68 100644 --- a/lib/features/settings/theme_remote_install_dialog.dart +++ b/lib/features/settings/theme_remote_install_dialog.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart' as material; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Dialog for installing a theme from a public HTTPS URL. Future showThemeRemoteInstallDialog( @@ -129,13 +130,15 @@ class _ThemeRemoteInstallDialogState ), ), actions: [ - OutlineButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.pop(context), - child: const material.Text('Cancel'), + size: QueryaControlSize.lg, ), - PrimaryButton( + QueryaButton.primary( + label: 'Install', onPressed: _submit, - child: const material.Text('Install'), + size: QueryaControlSize.lg, ), ], ); diff --git a/lib/features/workspace/sql_query_history_dialog.dart b/lib/features/workspace/sql_query_history_dialog.dart index 867e6136..577d05dc 100644 --- a/lib/features/workspace/sql_query_history_dialog.dart +++ b/lib/features/workspace/sql_query_history_dialog.dart @@ -7,6 +7,7 @@ import 'package:querya_desktop/core/storage/app_settings.dart'; import 'package:querya_desktop/core/storage/local_db.dart'; import 'package:querya_desktop/core/theme/querya_typography.dart'; import 'package:querya_desktop/shared/widgets/widgets.dart'; +import 'package:querya_desktop/core/ui/querya_control_tokens.dart'; /// Shows recent SQL for this connection + database; choosing a row replaces the editor text /// or prompts if the editor has uncommitted content. @@ -119,14 +120,16 @@ class _SqlQueryHistoryDialogContentState material.Row( mainAxisAlignment: material.MainAxisAlignment.end, children: [ - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(ctx).pop(false), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), const Gap(8), - DestructiveButton( + QueryaButton.destructive( + label: 'Clear', onPressed: () => material.Navigator.of(ctx).pop(true), - child: const Text('Clear'), + size: QueryaControlSize.lg, ), ], ), @@ -217,25 +220,29 @@ class _SqlQueryHistoryDialogContentState spacing: 8, runSpacing: 8, children: [ - GhostButton( + QueryaButton.ghost( + label: 'Cancel', onPressed: () => material.Navigator.of(ctx).pop(null), - child: const Text('Cancel'), + size: QueryaControlSize.lg, ), - OutlineButton( + QueryaButton.secondary( + label: 'Copy to Clipboard', onPressed: () => material.Navigator.of(ctx) .pop(_HistoryApplyAction.copy), - child: const Text('Copy to Clipboard'), + size: QueryaControlSize.lg, ), if (widget.onOpenInNewTab != null) - OutlineButton( + QueryaButton.secondary( + label: 'Open in New Tab', onPressed: () => material.Navigator.of(ctx) .pop(_HistoryApplyAction.openInNewTab), - child: const Text('Open in New Tab'), + size: QueryaControlSize.lg, ), - DestructiveButton( + QueryaButton.destructive( + label: 'Replace', onPressed: () => material.Navigator.of(ctx) .pop(_HistoryApplyAction.replace), - child: const Text('Replace'), + size: QueryaControlSize.lg, ), ], ), @@ -391,14 +398,16 @@ class _SqlQueryHistoryDialogContentState padding: const material.EdgeInsets.fromLTRB(16, 8, 16, 16), child: material.Row( children: [ - GhostButton( + QueryaButton.ghost( + label: 'Clear history', onPressed: () => unawaited(_confirmClear()), - child: const Text('Clear history'), + size: QueryaControlSize.lg, ), const Spacer(), - OutlineButton( + QueryaButton.ghost( + label: 'Close', onPressed: () => material.Navigator.of(context).pop(), - child: const Text('Close'), + size: QueryaControlSize.lg, ), ], ), From aff751b44f7fef2a270877480e27dbaf7586914b Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 11 Oct 2026 07:53:24 +0300 Subject: [PATCH 2/2] test: Create Index in the dialog is a QueryaButton now The dialog button moved to QueryaButton; the indexes view's own toolbar button is still a shadcn PrimaryButton, so the e2e flow taps one of each. --- .../04_nosql_workspaces/e2e_mongo_index_manager_test.dart | 3 ++- test/features/mongodb/mongo_indexes_view_test.dart | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/e2e/04_nosql_workspaces/e2e_mongo_index_manager_test.dart b/test/e2e/04_nosql_workspaces/e2e_mongo_index_manager_test.dart index 02a88ce0..a155ae23 100644 --- a/test/e2e/04_nosql_workspaces/e2e_mongo_index_manager_test.dart +++ b/test/e2e/04_nosql_workspaces/e2e_mongo_index_manager_test.dart @@ -67,6 +67,7 @@ void main() { expect(find.text('Indexes: orders'), findsOneWidget); expect(find.text('2 indexes'), findsOneWidget); + // The toolbar button of the indexes view (still a shadcn PrimaryButton). await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index')); await tester.pumpAndSettle(); expect(find.text('Collection: orders'), findsOneWidget); @@ -80,7 +81,7 @@ void main() { await tester.tap(find.text('Unique')); await tester.pumpAndSettle(); - await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index').last); + await tester.tap(find.widgetWithText(QueryaButton, 'Create Index').last); await tester.pumpAndSettle(); await tester.pump(const Duration(seconds: 5)); diff --git a/test/features/mongodb/mongo_indexes_view_test.dart b/test/features/mongodb/mongo_indexes_view_test.dart index ddf7421d..17b7e71f 100644 --- a/test/features/mongodb/mongo_indexes_view_test.dart +++ b/test/features/mongodb/mongo_indexes_view_test.dart @@ -191,7 +191,7 @@ void main() { expect(find.text('Collection: orders'), findsOneWidget); // Initially field name is empty, tap "Create Index" should trigger validation error - await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index')); + await tester.tap(find.widgetWithText(QueryaButton, 'Create Index')); await tester.pumpAndSettle(); expect(find.text('All field names must be specified'), findsOneWidget); @@ -207,7 +207,7 @@ void main() { await tester.pumpAndSettle(); // Submit - await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index')); + await tester.tap(find.widgetWithText(QueryaButton, 'Create Index')); await tester.pumpAndSettle(); await tester.pump(const Duration(seconds: 5)); @@ -273,7 +273,7 @@ void main() { await tester.pumpAndSettle(); // Submit - await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index')); + await tester.tap(find.widgetWithText(QueryaButton, 'Create Index')); await tester.pumpAndSettle(); await tester.pump(const Duration(seconds: 5));