Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fbf462a
theme: add Querya design tokens (querya_colors)
ZhuchkaTriplesix Apr 19, 2026
50378a8
theme: add Querya dark ColorScheme
ZhuchkaTriplesix Apr 19, 2026
1a545c2
theme: shared monospace stack for SQL editors
ZhuchkaTriplesix Apr 19, 2026
55dd7d0
theme: wire QueryaColorScheme and radius
ZhuchkaTriplesix Apr 19, 2026
05033aa
layout: responsive breakpoints and dialog insets
ZhuchkaTriplesix Apr 19, 2026
f6d6a0a
editor: placeholder for future SQL syntax highlighting
ZhuchkaTriplesix Apr 19, 2026
909ad5a
ui: SQL editor chrome with glow and inline decoration
ZhuchkaTriplesix Apr 19, 2026
8301367
connections: extract promptCreateConnection flow
ZhuchkaTriplesix Apr 19, 2026
b3abc60
ui: empty workspace hero and mock window
ZhuchkaTriplesix Apr 19, 2026
1e3ddc5
ui: apply SqlEditorChrome to query editor tab
ZhuchkaTriplesix Apr 19, 2026
1f84db5
ui: responsive SQL editor dialog chrome (PostgreSQL)
ZhuchkaTriplesix Apr 19, 2026
5229c19
ui: responsive SQL editor dialog chrome (MySQL)
ZhuchkaTriplesix Apr 19, 2026
4d7ff97
ui: SERVERS header, selection capsule, creation flow
ZhuchkaTriplesix Apr 19, 2026
ee6a28e
ui: title bar accent, borders, hero new connection flow
ZhuchkaTriplesix Apr 19, 2026
40f6bce
ui: show empty hero when no connection selected
ZhuchkaTriplesix Apr 19, 2026
91c0d37
test: workspace panel layout uses stub connection for splitter
ZhuchkaTriplesix Apr 19, 2026
e83e6e2
ui: adaptive database picker dialog and grid
ZhuchkaTriplesix Apr 19, 2026
3bf80b6
ui: adaptive dialog insets for driver manager
ZhuchkaTriplesix Apr 19, 2026
b3b1f6f
ui: adaptive dialog insets for new folder
ZhuchkaTriplesix Apr 19, 2026
487afb8
ui: adaptive dialog insets for PostgreSQL form
ZhuchkaTriplesix Apr 19, 2026
9015d22
ui: adaptive dialog insets for MySQL form
ZhuchkaTriplesix Apr 19, 2026
b26e9fb
ui: adaptive dialog insets for MongoDB form
ZhuchkaTriplesix Apr 19, 2026
f4c3011
ui: adaptive dialog insets for Redis form
ZhuchkaTriplesix Apr 19, 2026
61a0d34
ui: adaptive dialog insets for create MongoDB database
ZhuchkaTriplesix Apr 19, 2026
0a25ebc
ui: adaptive dialog insets for table privileges
ZhuchkaTriplesix Apr 19, 2026
27035d5
chore: update .gitignore
ZhuchkaTriplesix Apr 19, 2026
04b9d12
fix
ZhuchkaTriplesix Apr 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .flutter-plugins-dependencies
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"sqflite_darwin","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/sqflite_darwin-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"jni","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni_flutter","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni_flutter-1.0.1/","native_build":true,"dependencies":["jni"],"dev_dependency":false},{"name":"path_provider_android","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_android-2.3.1/","native_build":false,"dependencies":["jni","jni_flutter"],"dev_dependency":false},{"name":"sqflite_android","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/sqflite_android-2.4.2+3/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"bitsdojo_window_macos","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/bitsdojo_window_macos-0.1.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"sqflite_darwin","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/sqflite_darwin-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"bitsdojo_window_linux","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/bitsdojo_window_linux-0.1.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"bitsdojo_window_windows","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/bitsdojo_window_windows-0.1.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"web":[]},"dependencyGraph":[{"name":"bitsdojo_window","dependencies":["bitsdojo_window_windows","bitsdojo_window_macos","bitsdojo_window_linux"]},{"name":"bitsdojo_window_linux","dependencies":[]},{"name":"bitsdojo_window_macos","dependencies":[]},{"name":"bitsdojo_window_windows","dependencies":[]},{"name":"jni","dependencies":[]},{"name":"jni_flutter","dependencies":["jni"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":["jni","jni_flutter"]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":["sqflite_android","sqflite_darwin"]},{"name":"sqflite_android","dependencies":[]},{"name":"sqflite_darwin","dependencies":[]}],"date_created":"2026-04-11 12:30:47.798124","version":"3.41.6","swift_package_manager_enabled":{"ios":false,"macos":false}}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"sqflite_darwin","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/sqflite_darwin-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"jni","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni_flutter","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni_flutter-1.0.1/","native_build":true,"dependencies":["jni"],"dev_dependency":false},{"name":"path_provider_android","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_android-2.3.1/","native_build":false,"dependencies":["jni","jni_flutter"],"dev_dependency":false},{"name":"sqflite_android","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/sqflite_android-2.4.2+3/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"bitsdojo_window_macos","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/bitsdojo_window_macos-0.1.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"sqflite_darwin","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/sqflite_darwin-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"bitsdojo_window_linux","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/bitsdojo_window_linux-0.1.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"bitsdojo_window_windows","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/bitsdojo_window_windows-0.1.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/home/zhuchka/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"web":[]},"dependencyGraph":[{"name":"bitsdojo_window","dependencies":["bitsdojo_window_windows","bitsdojo_window_macos","bitsdojo_window_linux"]},{"name":"bitsdojo_window_linux","dependencies":[]},{"name":"bitsdojo_window_macos","dependencies":[]},{"name":"bitsdojo_window_windows","dependencies":[]},{"name":"jni","dependencies":[]},{"name":"jni_flutter","dependencies":["jni"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":["jni","jni_flutter"]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":["sqflite_android","sqflite_darwin"]},{"name":"sqflite_android","dependencies":[]},{"name":"sqflite_darwin","dependencies":[]}],"date_created":"2026-04-19 12:51:07.216547","version":"3.41.6","swift_package_manager_enabled":{"ios":false,"macos":false}}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ Thumbs.db
*.dll
*.exe
flutter_*.log
design-front
7 changes: 7 additions & 0 deletions lib/core/editor/sql_syntax_highlighting.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// Future work: editable SQL with syntax highlighting (see plan: syntax-highlight-epic).
///
/// Candidates: custom [EditableText] + [TextPainter], or a dedicated code-editor package.
/// Plain [TextField] remains the source of truth until an editor is chosen.
abstract class SqlSyntaxHighlighting {
const SqlSyntaxHighlighting._();
}
81 changes: 81 additions & 0 deletions lib/core/layout/window_layout.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'dart:math' as math;

import 'package:flutter/widgets.dart';

/// Breakpoints and sizes derived from window / overlay size (desktop adaptive UI).
abstract class WindowLayout {
WindowLayout._();

static const double narrowWindowWidth = 720;
static const double compactWindowWidth = 520;

/// Horizontal inset for modal dialogs (clamped by screen).
static double dialogHorizontalInset(double screenWidth) {
return (screenWidth * 0.05).clamp(12.0, 48.0);
}

static double dialogVerticalInset(double screenHeight) {
return (screenHeight * 0.04).clamp(12.0, 40.0);
}

/// Use for [Dialog.insetPadding] / modal margins on small windows.
static EdgeInsets dialogSymmetricInsets(BuildContext context) {
final mq = MediaQuery.sizeOf(context);
return EdgeInsets.symmetric(
horizontal: dialogHorizontalInset(mq.width),
vertical: dialogVerticalInset(mq.height),
);
}

/// "Select database" and similar pickers.
static double newConnectionDialogMaxWidth(double screenWidth) {
final inset = dialogHorizontalInset(screenWidth) * 2;
return math.min(740, math.max(280.0, screenWidth - inset));
}

static double newConnectionDialogHeight(double screenHeight) {
final inset = dialogVerticalInset(screenHeight) * 2;
final h = screenHeight - inset;
return math.min(580, math.max(320.0, h * 0.78));
}

static double newConnectionSidebarWidth(double dialogWidth) {
if (dialogWidth < 400) return 88;
if (dialogWidth < 520) return 108;
if (dialogWidth < 640) return 124;
return 140;
}

/// Grid area width (right of sidebar, inner padding applied separately).
static int dbTypeGridCrossAxisCount(double gridInnerWidth) {
if (gridInnerWidth >= 460) return 4;
if (gridInnerWidth >= 240) return 2;
return 1;
}

static double dbTypeCardHeight(int crossAxisCount) {
return switch (crossAxisCount) {
4 => 144,
2 => 138,
_ => 132,
};
}

/// Empty workspace hero content max width (stays within viewport minus padding).
static double heroContentMaxWidth(double viewportWidth) {
final pad = heroHorizontalPadding(viewportWidth) * 2;
final inner = math.max(0.0, viewportWidth - pad);
return math.min(560, inner);
}

static double heroHorizontalPadding(double viewportWidth) {
if (viewportWidth < compactWindowWidth) return 16;
if (viewportWidth < narrowWindowWidth) return 22;
return 28;
}

/// Mock window block height scales with available width.
static double heroMockWindowHeight(double contentWidth) {
return (contentWidth * 0.38).clamp(140.0, 220.0);
}
}
6 changes: 4 additions & 2 deletions lib/core/theme/app_theme.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'package:shadcn_flutter/shadcn_flutter.dart';

import 'querya_color_scheme.dart';

/// App theme: dark only. Used for both theme and darkTheme so the app is always dark.
abstract class AppTheme {
static ThemeData get dark => const ThemeData.dark(
colorScheme: ColorSchemes.darkSlate,
radius: 0.5,
colorScheme: QueryaColorScheme.dark,
radius: 0.58,
scaling: 1,
typography: Typography.geist(),
);
Expand Down
34 changes: 34 additions & 0 deletions lib/core/theme/querya_color_scheme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:shadcn_flutter/shadcn_flutter.dart';

import 'querya_colors.dart';

/// Dark [ColorScheme] for Querya desktop — matches [QueryaColors] tokens.
abstract class QueryaColorScheme {
static const ColorScheme dark = ColorScheme(
brightness: Brightness.dark,
background: QueryaColors.canvas,
foreground: Color(0xFFF8FAFC),
card: QueryaColors.surface,
cardForeground: Color(0xFFF8FAFC),
popover: QueryaColors.surface,
popoverForeground: Color(0xFFF8FAFC),
primary: QueryaColors.accentCyan,
primaryForeground: QueryaColors.onAccent,
secondary: Color(0xFF18181B),
secondaryForeground: Color(0xFFF8FAFC),
muted: Color(0xFF18181B),
mutedForeground: QueryaColors.mutedLabel,
accent: Color(0xFF27272A),
accentForeground: Color(0xFFF8FAFC),
destructive: Color(0xFFEF4444),
destructiveForeground: Color(0xFFF8FAFC),
border: QueryaColors.borderSubtle,
input: QueryaColors.borderSubtle,
ring: QueryaColors.accentCyan,
chart1: Color(0xFF2662D9),
chart2: Color(0xFF2EB88A),
chart3: Color(0xFFE88C30),
chart4: Color(0xFFAF57DB),
chart5: Color(0xFFE23670),
);
}
27 changes: 27 additions & 0 deletions lib/core/theme/querya_colors.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'dart:ui';

/// Design tokens aligned with [design-front] mockups (near-black canvas, cyan accent).
///
/// Canonical semantic mapping lives in [QueryaColorScheme]; these are named aliases
/// for documentation and for a few widgets that need the raw accent (e.g. glows).
abstract class QueryaColors {
QueryaColors._();

/// Main app background — pure black on reference hero.
static const Color canvas = Color(0xFF000000);

/// Elevated surface (cards, mock window chrome).
static const Color surface = Color(0xFF0C0C0C);

/// Brand accent (CTAs, tree icons, focus ring).
static const Color accentCyan = Color(0xFF22D3EE);

/// Text / icons on filled primary buttons.
static const Color onAccent = Color(0xFF0A0A0A);

/// Hairline borders on dark UI.
static const Color borderSubtle = Color(0xFF27272A);

/// Secondary label tone (body muted on mockups).
static const Color mutedLabel = Color(0xFF94A3B8);
}
6 changes: 6 additions & 0 deletions lib/core/theme/querya_typography.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// Monospace stack for SQL editors (bundled font can replace this later).
abstract class QueryaTypography {
QueryaTypography._();

static const String mono = 'monospace';
}
28 changes: 28 additions & 0 deletions lib/features/connections/connection_creation_flow.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart' as material;

import 'package:querya_desktop/core/storage/local_db.dart';
import 'package:querya_desktop/features/connections/new_connection_dialog.dart';
import 'package:querya_desktop/features/mongodb/mongodb_connection_form.dart';
import 'package:querya_desktop/features/mysql/mysql_connection_form.dart';
import 'package:querya_desktop/features/postgresql/postgresql_connection_form.dart';
import 'package:querya_desktop/features/redis/redis_connection_form.dart';

/// Picks a database type, opens the matching form, returns a saved row or null.
Future<ConnectionRow?> promptCreateConnection(
material.BuildContext context, {
int? folderId,
}) async {
final type = await showNewConnectionDialog(context);
if (type == null) return null;
if (!context.mounted) return null;
switch (type) {
case ConnectionType.postgresql:
return await showPostgresConnectionForm(context, folderId: folderId);
case ConnectionType.mysql:
return await showMysqlConnectionForm(context, folderId: folderId);
case ConnectionType.mongodb:
return await showMongoConnectionForm(context, folderId: folderId);
case ConnectionType.redis:
return await showRedisConnectionForm(context, folderId: folderId);
}
}
Loading
Loading