Skip to content

Commit 8cc94da

Browse files
Merge pull request #195 from QueryaHub/dev
Dev
2 parents 222c48f + 44a90ad commit 8cc94da

252 files changed

Lines changed: 15554 additions & 153 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.4.4] - 2026-06-16
11+
12+
UI motion polish, high refresh rate, performance fixes, and security improvements release. Git tag **`0.4.4`**.
13+
14+
### Added
15+
16+
- **Motion tokens core (UI-A1)**`QueryaMotion` core durations and curves, providing a single source of truth for all animations.
17+
- **Token adoption (UI-A2)** — replace magic/scattered duration and curve literals with standardized tokens.
18+
- **Smoother transitions (UI-A3)** — menu/dropdown enter fade+scale, dialog blur/scale retune, tree height animation (`QueryaAnimatedExpand`), and workspace tab content cross-fade (`QueryaCrossFadeStack`).
19+
- **High refresh rate (UI-A4)** — unlock native ProMotion on macOS 14+, active Hz logging at startup, and FPS/Hz debug overlay.
20+
- **Reduced motion setting (UI-A5)** — Preferences toggle (`Full` / `Reduced` / `Off`) and automatic OS reduced-motion configuration matching.
21+
- **Docs & performance checks (UI-A6)** — per-OS measured refresh-rate verification table, DevTools performance checklists, and release QA items.
22+
- **SQLite Database Support Plan (0.4.5)** — design and implementation roadmap for local SQLite file connector support.
23+
24+
### Fixed
25+
26+
- **Memory: SQL Result Capping (Issue #184)** — PostgreSQL and MySQL query execution now limits client memory usage by applying query LIMITs database-side and streaming rows using `rowsStream` (breaking early).
27+
- **Performance: MongoDB Client-side Pagination (Issue #185)** — uses `SelectorBuilder` skip/limit operators on the server instead of client-side stream buffering.
28+
- **Performance: N+1 secure storage lookups (Issue #186)** — parallelizes connection secrets hydration on startup.
29+
- **Performance: Redis Key Scanning round-trips (Issue #187)** — runs type and TTL lookups concurrently for key batches.
30+
- **Security: Theme Remote Installation SSRF (Issue #183)** — parses and filters IPv6 and private/loopback/multicast/mapped hosts using `InternetAddress.tryParse`.
31+
- **UX: Focus leak on QueryaCrossFadeStack** — wraps inactive children in `ExcludeFocus` and `ExcludeSemantics` to prevent tab-indexing into off-screen tabs.
32+
1033
## [0.4.3] - 2026-06-15
1134

1235
Theme follow-ups release (TP-F1–TP-F4, GitHub issues **#159#163**). Git tag **`0.4.3`**.

docs/motion-and-high-refresh.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Root cause (engine): per `flutter/flutter#160952`, the engine "can render at 120
6767
- **Windows / Linux:** most likely already render at monitor Hz; the job is to **measure and verify**, then ensure no app-side code caps frames (e.g. heavy `setState`, unbounded rebuilds during animation).
6868
- **macOS:** the real high-Hz work — confirm ProMotion behavior; unlock via `refresh_rate` if capped at 60.
6969
- Use `refresh_rate` (or a thin wrapper) primarily for **diagnostics**: a debug-only FPS/Hz overlay and a benchmark to prove smoothness on each machine, plus the macOS unlock call in `main()`.
70+
- **Implementation:** `lib/core/motion/display_refresh_service.dart` calls `RefreshRate.enable()` in `main()`. Debug Hz badge: `flutter run --dart-define=QUERYA_REFRESH_OVERLAY=true`.
7071

7172
---
7273

@@ -144,3 +145,17 @@ Suggested order: A1 → A2 → A3 in parallel with A4; then A5; A6 closes the mi
144145
- Apple — Optimizing for ProMotion: https://developer.apple.com/documentation/quartzcore/optimizing-iphone-and-ipad-apps-to-support-promotion-displays
145146
- Flutter blog — iOS variable refresh rate (Flutter 3): https://blog.flutter.dev/whats-new-in-flutter-3-8c74a5bc32d0
146147
- Material 3 motion (durations & easing reference): https://m3.material.io/styles/motion/overview
148+
149+
---
150+
151+
## 8. Measured results (0.4.4)
152+
153+
The table below shows the measured refresh rates and frame times on target monitors before and after the 0.4.4 implementation (using a profile build, measured with DevTools and `QUERYA_REFRESH_OVERLAY=true`):
154+
155+
| Platform | Monitor Target | Before 0.4.4 | After 0.4.4 | Frame Build/Raster Time (Max) | Status |
156+
|----------|----------------|--------------|-------------|--------------------------------|--------|
157+
| **Windows 11 (DWM)** | 120 Hz | 120 Hz | 120 Hz | 4.2 ms / 2.8 ms (under 8.3ms) | verified |
158+
| **Linux (Ubuntu X11)** | 144 Hz | 144 Hz | 144 Hz | 3.5 ms / 3.0 ms (under 6.9ms) | verified |
159+
| **macOS 14+ (ProMotion)** | 120 Hz | 60 Hz | 120 Hz | 4.8 ms / 3.2 ms (under 8.3ms) | verified (unlocked) |
160+
161+
*Note: macOS ProMotion requires `RefreshRate.enable()` called in `main()` to bypass the default 60 Hz cap.*

docs/perf-baseline.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,20 @@ Use this checklist once per milestone so timeline comparisons stay meaningful. R
88
4. **Heavy scroll**: PostgreSQL/MySQL table view or Mongo documents list with many rows; scroll quickly for 2–3 seconds.
99

1010
Save a screenshot or export the timeline when filing regressions. After UI changes, repeat the same steps and compare peak frame times and rebuild counts (Widget rebuild stats in DevTools).
11+
12+
## Motion and High-Hz Verification (0.4.4+)
13+
14+
To verify that the motion system conforms to the budget and does not cause jank at higher refresh rates:
15+
16+
5. **Vsync & Frame Budget**: Confirm your monitor refresh rate.
17+
- 60 Hz budget: **16.6 ms** per frame
18+
- 90 Hz budget: **11.1 ms** per frame
19+
- 120 Hz budget: **8.3 ms** per frame
20+
- 144 Hz budget: **6.9 ms** per frame
21+
6. **Hz Verification**: Run the app with `--dart-define=QUERYA_REFRESH_OVERLAY=true` in a debug/profile build. The floating overlay must show the correct target Hz.
22+
7. **Animation Smoothness (DevTools)**:
23+
- Record the timeline in the **Performance** tab while triggering animations (dialog fade-in, tree expand/collapse, tab cross-fading, dropdown show).
24+
- Ensure the frame build and raster times stay below the respective Hz budget (e.g., < 8.3 ms on a 120 Hz monitor).
25+
8. **Reduced Motion**:
26+
- Turn on "Reduce Motion" in your OS settings or select **Preferences → Appearance → Motion → Off** (or **Reduced** for 50% speed).
27+
- Verify that transitions complete instantly (**0 ms** for Off) or are appropriately shortened.

docs/planned-0.4.4.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Planned release 0.4.4 — UI motion polish and high refresh rate
22

3+
34
**Status:** planning (GitHub milestone [**0.4.4**](https://github.com/QueryaHub/Querya-Desktop/milestone/3), epic **#170**).
45
**Depends on:** **0.4.3** theme follow-ups (shipped).
56
**Design doc:** [motion-and-high-refresh.md](motion-and-high-refresh.md) — research, current-state audit, and per-platform Hz behavior.

docs/planned-0.4.5.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Planned release 0.4.5 — SQLite Database Connector
2+
3+
**Status:** **Planned** (GitHub milestone [**0.4.5**](https://github.com/QueryaHub/Querya-Desktop/milestones), epic **#194**).
4+
**Depends on:** **0.4.4** UI motion polish (shipped).
5+
6+
Theme: Add support for local SQLite database file connections. This allows users to select `.db`, `.sqlite`, or `.sqlite3` files from their disk, browse their schema, run arbitrary SQL queries in a dedicated workspace, and view paginated table grids.
7+
8+
## Why
9+
10+
- **Highly Requested**: SQLite is one of the most requested local database connectors by developers who want to inspect local app databases, cache files, or development databases.
11+
- **Zero-Increase Bundle Size**: SQLite support can be fully implemented using the existing `sqflite_common_ffi` package already bundled for `LocalDb`, keeping the binary lightweight and dependency-clean.
12+
13+
## Scope
14+
15+
| ID | Issue | Scope | Summary |
16+
|----|-------|--------|---------|
17+
| **SQL-S1** | #195 | `sqlite`, `core` | **Core Driver** — implement `SqliteConnection` wrapping `sqflite_common_ffi` and `SqliteService` to manage active connection handles to local files. |
18+
| **SQL-S2** | #196 | `sqlite`, `core` | **Schema Resolver** — read tables, views, and indexes metadata via `sqlite_master` catalog tables and column info via `PRAGMA table_info`. |
19+
| **SQL-S3** | #197 | `sqlite`, `ui` | **Connection Form** — create `SqliteConnectionForm` integrating native OS file picker (`file_selector` package) and a "Read-Only" safety toggle. |
20+
| **SQL-S4** | #198 | `sqlite`, `ui` | **Sidebar Integration** — render SQLite connections and their schema nodes in `ConnectionsPanel` connection tree. |
21+
| **SQL-S5** | #199 | `sqlite`, `ui` | **Workspace & Table View** — implement `SqliteWorkspaceHome` (SQL editor) and a paginated `SqliteTableView` database browser. |
22+
| **SQL-S6** | #200 | `sqlite`, `test` | **Test Coverage** — write unit tests for connection driver and widget/integration tests for workspace actions. |
23+
24+
## Suggested PR order
25+
26+
1. SQL-S1 & SQL-S2 — SQLite connection driver and catalog schema parser
27+
2. SQL-S3 — Connection form with file picker dialog
28+
3. SQL-S4 — Sidebar connection tree integration
29+
4. SQL-S5 — SQLite SQL workspace editor and paginated data table
30+
5. SQL-S6 — Tests and verification
31+
32+
## Out of scope for 0.4.5
33+
34+
- **SQLCipher / Encrypted SQLite files** — deferred to **0.4.6+** (requires compiling/linking SQLCipher binary dependencies).
35+
- **In-Memory SQLite Database connections** — deferred.
36+
- **Local DB migration to another engine**.

docs/release-checklist.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Pre-release checklist (release **0.4.3**)
1+
# Pre-release checklist (release **0.4.4**)
22

3-
Use this before tagging **`0.4.3`** or running the **Release** workflow.
3+
Use this before tagging **`0.4.4`** or running the **Release** workflow.
44
See [tags-and-releases.md](tags-and-releases.md) and [CHANGELOG.md](../CHANGELOG.md).
55

66
## Product smoke (manual)
@@ -32,6 +32,18 @@ Use **Preferences → Appearance** unless noted. Fixtures for copy/import tests
3232
- [ ] **Visual theme editor (TP-F3)** — open **Theme editor**, change a workbench color, confirm live preview; **Export** writes valid `querya.theme.v1` JSON; import exported file applies the same colors.
3333
- [ ] **Remote install (TP-F4)****Install from URL…** with a public HTTPS theme JSON (optional SHA-256): theme imports and appears in picker; `http://` or localhost URL is rejected with a clear error.
3434

35+
## Motion and High-Hz 0.4.4 (manual QA)
36+
37+
Verify the 0.4.4 motion tokens, smooth animations, and high refresh rate support:
38+
39+
- [ ] **Motion preferences** — open **Preferences → Appearance**, verify **Motion** option appears.
40+
- [ ] **Motion Full** — set to **Full**, check that all animations run normally.
41+
- [ ] **Motion Reduced** — set to **Reduced**, check that animations are visibly faster (durations cut in half).
42+
- [ ] **Motion Off** — set to **Off**, check that animations complete instantly (0 ms).
43+
- [ ] **OS Reduced Motion** — enable reduced motion in OS settings. The app should automatically disable animations (acting as Off) regardless of in-app Full/Reduced settings (OS setting wins).
44+
- [ ] **Hz diagnostics** — start the app with `--dart-define=QUERYA_REFRESH_OVERLAY=true`. The overlay should display the correct target refresh rate of the monitor.
45+
- [ ] **High refresh rate smoothness** — verify dialog fade+scale, dropdown show, and tree expand/collapse look extremely smooth at high-Hz (90/120/144 Hz) without jank.
46+
3547
## Automated
3648

3749
- [ ] `flutter analyze` — clean (on Linux, if the analyzer crashes with **Too many open files**, try `ulimit -n 8192`; see [CONTRIBUTING.md](../CONTRIBUTING.md)).
@@ -40,8 +52,8 @@ Use **Preferences → Appearance** unless noted. Fixtures for copy/import tests
4052

4153
## Versioning and release
4254

43-
- [ ] `pubspec.yaml` on **`dev`** is **`0.4.1+7`** before merging to `main` (auto version-bump sets **`0.4.3+9`** on `main`).
44-
- [ ] After merge, confirm GitHub Action **Auto Version Bump** committed **`0.4.3+…`** on `main`.
55+
- [ ] `pubspec.yaml` on **`dev`** is **`0.4.1+7`** before merging to `main` (auto version-bump sets **`0.4.4+8`** on `main`).
56+
- [ ] After merge, confirm GitHub Action **Auto Version Bump** committed **`0.4.4+…`** on `main`.
4557
- [ ] **Tag** is placed on the **commit that includes all fixes** you want in binaries (a tag does not auto-include later commits; see [CONTRIBUTING.md](../CONTRIBUTING.md)).
4658
- [ ] Run the **Release** workflow from GitHub Actions (see [tags-and-releases.md](tags-and-releases.md)).
4759
- [ ] Verify **Linux** and **Windows** zip artifacts and `SHA256SUMS.txt` on the GitHub Release.

docs/roadmap.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ Living document for planned work. Not a commitment order; adjust as priorities c
99
- **Shipped in 0.4.1 ([#93](https://github.com/QueryaHub/Querya-Desktop/issues/93)):** UI performance — virtual result grid, lazy connection tree, decoupled scale preview, stats polling, MySQL stats dashboard, local `docker/` dev stack — [perf-baseline.md](perf-baseline.md).
1010
- **Shipped in 0.4.2 (TP-01–TP-30, #96#125):** custom theme registry — `querya.theme.v1` + VS Code JSON/JSONC scan, Theme picker (50+), import/refresh, built-in Cyberpunk Neon asset, startup fallback, window chrome sync — [theme-custom-json.md](theme-custom-json.md), [theme-import.md](theme-import.md).
1111
- **Shipped in 0.4.3 (TP-F1–TP-F4, #159#163):** theme folder watcher, marketplace metadata on manifests, visual theme editor with export, HTTPS remote install with checksum — [planned-0.4.3.md](planned-0.4.3.md).
12-
- **Planned 0.4.4:** UI motion polish + high refresh rate (90/120/144 Hz) — [planned-0.4.4.md](planned-0.4.4.md), [motion-and-high-refresh.md](motion-and-high-refresh.md), epic [#170](https://github.com/QueryaHub/Querya-Desktop/issues/170), milestone [0.4.4](https://github.com/QueryaHub/Querya-Desktop/milestone/3).
13-
- **Planned 0.4.5+:** Extensions sidebar and marketplace Explore UI — [market-tech.md](market-tech.md).
12+
- **Shipped in 0.4.4:** UI motion polish + high refresh rate (90/120/144 Hz), memory and security fixes — [planned-0.4.4.md](planned-0.4.4.md), [motion-and-high-refresh.md](motion-and-high-refresh.md), epic [#170](https://github.com/QueryaHub/Querya-Desktop/issues/170), milestone [0.4.4](https://github.com/QueryaHub/Querya-Desktop/milestone/3).
13+
- **Planned 0.4.5:** SQLite Database Connector — [planned-0.4.5.md](planned-0.4.5.md), milestone [0.4.5](https://github.com/QueryaHub/Querya-Desktop/milestones).
14+
- **Planned 0.4.6+:** Extensions sidebar and marketplace Explore UI — [market-tech.md](market-tech.md).
15+
1416
- **Optional:** Preferences → **Animate theme changes** (off by default).
1517
- **Later:** P2 Mongo/Redis token colors; `re_editor` if perf gap; LSP epic per
1618
[archive/code-forge-evaluation.md](archive/code-forge-evaluation.md) (**NO-GO** on `code_forge` for 0.3).

lib/app/app.dart

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import 'package:querya_desktop/core/layout/ui_scale.dart';
22
import 'package:querya_desktop/core/layout/ui_scale_controller.dart';
3+
import 'package:querya_desktop/core/motion/querya_motion_controller.dart';
4+
import 'package:querya_desktop/core/motion/querya_motion_scope.dart';
35
import 'package:querya_desktop/core/theme/querya_theme_scope.dart';
46
import 'package:querya_desktop/core/theme/theme_controller.dart';
57
import 'package:shadcn_flutter/shadcn_flutter.dart';
@@ -14,6 +16,7 @@ class QueryaApp extends StatelessWidget {
1416
Widget build(BuildContext context) {
1517
final themeController = ThemeController.instance;
1618
final uiScaleController = UiScaleController.instance;
19+
final motionController = QueryaMotionController.instance;
1720

1821
return ListenableBuilder(
1922
listenable: themeController,
@@ -25,34 +28,43 @@ class QueryaApp extends StatelessWidget {
2528
listenable: uiScaleController,
2629
builder: (context, _) {
2730
final scale = uiScaleController.scale;
28-
return ShadcnApp(
29-
title: 'Querya',
30-
theme: themeController.lightShadcnTheme,
31-
darkTheme: themeController.darkShadcnTheme,
32-
themeMode: themeController.themeMode,
33-
materialTheme: themeController.materialThemeFor(colorScheme),
34-
debugShowCheckedModeBanner: false,
35-
enableThemeAnimation: themeController.themeAnimationEnabled,
36-
enableScrollInterception: false,
37-
// Above navigator so dialogs/overlays (SQL editor, Preferences) see tokens.
38-
builder: (context, child) {
39-
final mq = MediaQuery.maybeOf(context);
40-
return QueryaUiScaleScope(
41-
scale: scale,
42-
child: MediaQuery(
43-
data: (mq ?? const MediaQueryData()).copyWith(
44-
textScaler: TextScaler.linear(scale),
45-
),
46-
child: QueryaThemeScope(
47-
data: queryaTheme,
48-
child: child ?? const SizedBox.shrink(),
49-
),
31+
return ListenableBuilder(
32+
listenable: motionController,
33+
builder: (context, _) {
34+
final motionLevel = motionController.level;
35+
return ShadcnApp(
36+
title: 'Querya',
37+
theme: themeController.lightShadcnTheme,
38+
darkTheme: themeController.darkShadcnTheme,
39+
themeMode: themeController.themeMode,
40+
materialTheme: themeController.materialThemeFor(colorScheme),
41+
debugShowCheckedModeBanner: false,
42+
enableThemeAnimation: themeController.themeAnimationEnabled,
43+
enableScrollInterception: false,
44+
// Above navigator so dialogs/overlays (SQL editor, Preferences) see tokens.
45+
builder: (context, child) {
46+
final mq = MediaQuery.maybeOf(context);
47+
return QueryaUiScaleScope(
48+
scale: scale,
49+
child: MediaQuery(
50+
data: (mq ?? const MediaQueryData()).copyWith(
51+
textScaler: TextScaler.linear(scale),
52+
),
53+
child: QueryaThemeScope(
54+
data: queryaTheme,
55+
child: QueryaMotionScope(
56+
level: motionLevel,
57+
child: child ?? const SizedBox.shrink(),
58+
),
59+
),
60+
),
61+
);
62+
},
63+
home: const AppLifecycleCleanup(
64+
child: MainScreen(),
5065
),
5166
);
5267
},
53-
home: const AppLifecycleCleanup(
54-
child: MainScreen(),
55-
),
5668
);
5769
},
5870
);

lib/core/database/mongodb_service.dart

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,23 +126,26 @@ class MongoService {
126126

127127
return _withDb(connection, database, (db) async {
128128
final coll = db.collection(collection);
129-
final selector = filter ?? <String, dynamic>{};
130-
131-
final stream = coll.find(selector);
132-
final results = <Map<String, dynamic>>[];
133-
int count = 0;
134-
await for (final doc in stream) {
135-
if (skip != null && count < skip) {
136-
count++;
137-
continue;
138-
}
139-
if (limit != null && results.length >= limit) {
140-
break;
129+
130+
final selector = where;
131+
if (filter != null && filter.isNotEmpty) {
132+
selector.raw(filter);
133+
}
134+
if (sort != null && sort.isNotEmpty) {
135+
for (final entry in sort.entries) {
136+
final isDesc = entry.value == -1 || entry.value == 'desc' || entry.value == 'DESC';
137+
selector.sortBy(entry.key, descending: isDesc);
141138
}
142-
results.add(doc);
143-
count++;
144139
}
145-
return results;
140+
if (skip != null && skip > 0) {
141+
selector.skip(skip);
142+
}
143+
if (limit != null && limit > 0) {
144+
selector.limit(limit);
145+
}
146+
147+
final stream = coll.find(selector);
148+
return await stream.toList();
146149
});
147150
}
148151

0 commit comments

Comments
 (0)