Skip to content
Merged

Dev #195

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
28a2678
docs: link 0.4.4 milestone issues #170–#176 in planning docs
ZhuchkaTriplesix Jun 15, 2026
980f36c
feat(motion): add QueryaMotion tokens and reduced-motion helpers
ZhuchkaTriplesix Jun 15, 2026
95002e6
Merge pull request #177 from QueryaHub/issue/173-motion-tokens-core
ZhuchkaTriplesix Jun 15, 2026
fce7b59
refactor(motion): adopt QueryaMotion tokens across UI widgets
ZhuchkaTriplesix Jun 15, 2026
c5eac0f
Merge pull request #178 from QueryaHub/issue/171-adopt-motion-tokens
ZhuchkaTriplesix Jun 15, 2026
fbe8d1d
feat(motion): smoother transitions for menus, tree, and tabs
ZhuchkaTriplesix Jun 15, 2026
8a89ea0
Merge pull request #179 from QueryaHub/issue/172-smoother-transitions
ZhuchkaTriplesix Jun 15, 2026
f4d2f31
feat(motion): enable high refresh rate via refresh_rate
ZhuchkaTriplesix Jun 15, 2026
014597e
Merge pull request #180 from QueryaHub/issue/174-high-refresh-rate
ZhuchkaTriplesix Jun 15, 2026
db32374
feat(motion): implement reduced motion toggle and preferences setting…
ZhuchkaTriplesix Jun 16, 2026
a18c1c3
feat(motion): commit refresh_rate package override source and generat…
ZhuchkaTriplesix Jun 16, 2026
d6aa684
Merge pull request #181 from QueryaHub/issue/175-reduced-motion
ZhuchkaTriplesix Jun 16, 2026
2aa48fc
docs: document 0.4.4 release and update performance checks (Closes #176)
ZhuchkaTriplesix Jun 16, 2026
425106e
Merge pull request #182 from QueryaHub/issue/176-release-docs
ZhuchkaTriplesix Jun 16, 2026
fe91e3a
perf(postgresql,mysql): limit SQL result memory usage
ZhuchkaTriplesix Jun 16, 2026
96bb952
Merge pull request #188 from QueryaHub/issue/184-sql-result-capping-m…
ZhuchkaTriplesix Jun 16, 2026
9bbd1ca
perf(mongodb): execute skip and limit pagination database-side
ZhuchkaTriplesix Jun 16, 2026
9493174
Merge pull request #189 from QueryaHub/issue/185-mongodb-client-side-…
ZhuchkaTriplesix Jun 16, 2026
bf61b49
perf(connections): load connection secrets concurrently on startup
ZhuchkaTriplesix Jun 16, 2026
cf55d5f
Merge pull request #190 from QueryaHub/issue/186-secure-storage-n-plus-1
ZhuchkaTriplesix Jun 16, 2026
9757b3a
perf(redis): query key types and TTLs concurrently during scan
ZhuchkaTriplesix Jun 16, 2026
13ffaa4
Merge pull request #191 from QueryaHub/issue/187-redis-scanner-concur…
ZhuchkaTriplesix Jun 16, 2026
6977ace
fix(theme): prevent remote theme installation SSRF via IPv6 addresses
ZhuchkaTriplesix Jun 16, 2026
4c382eb
Merge pull request #192 from QueryaHub/issue/183-remote-theme-ssrf-ipv6
ZhuchkaTriplesix Jun 16, 2026
d5205b2
fix(motion): exclude focus and semantics on inactive QueryaCrossFadeS…
ZhuchkaTriplesix Jun 16, 2026
93db72e
Merge pull request #193 from QueryaHub/issue/172-cross-fade-focus-exc…
ZhuchkaTriplesix Jun 16, 2026
7cf94c5
docs: add release 0.4.5 SQLite integration plan and update changelog
ZhuchkaTriplesix Jun 16, 2026
6b086ad
Merge pull request #194 from QueryaHub/docs/planned-0.4.5
ZhuchkaTriplesix Jun 16, 2026
037848d
chore(release): prep release 0.4.4 documentation updates
ZhuchkaTriplesix Jun 16, 2026
44a90ad
Merge branch 'main' into dev
ZhuchkaTriplesix Jun 16, 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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.4.4] - 2026-06-16

UI motion polish, high refresh rate, performance fixes, and security improvements release. Git tag **`0.4.4`**.

### Added

- **Motion tokens core (UI-A1)** — `QueryaMotion` core durations and curves, providing a single source of truth for all animations.
- **Token adoption (UI-A2)** — replace magic/scattered duration and curve literals with standardized tokens.
- **Smoother transitions (UI-A3)** — menu/dropdown enter fade+scale, dialog blur/scale retune, tree height animation (`QueryaAnimatedExpand`), and workspace tab content cross-fade (`QueryaCrossFadeStack`).
- **High refresh rate (UI-A4)** — unlock native ProMotion on macOS 14+, active Hz logging at startup, and FPS/Hz debug overlay.
- **Reduced motion setting (UI-A5)** — Preferences toggle (`Full` / `Reduced` / `Off`) and automatic OS reduced-motion configuration matching.
- **Docs & performance checks (UI-A6)** — per-OS measured refresh-rate verification table, DevTools performance checklists, and release QA items.
- **SQLite Database Support Plan (0.4.5)** — design and implementation roadmap for local SQLite file connector support.

### Fixed

- **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).
- **Performance: MongoDB Client-side Pagination (Issue #185)** — uses `SelectorBuilder` skip/limit operators on the server instead of client-side stream buffering.
- **Performance: N+1 secure storage lookups (Issue #186)** — parallelizes connection secrets hydration on startup.
- **Performance: Redis Key Scanning round-trips (Issue #187)** — runs type and TTL lookups concurrently for key batches.
- **Security: Theme Remote Installation SSRF (Issue #183)** — parses and filters IPv6 and private/loopback/multicast/mapped hosts using `InternetAddress.tryParse`.
- **UX: Focus leak on QueryaCrossFadeStack** — wraps inactive children in `ExcludeFocus` and `ExcludeSemantics` to prevent tab-indexing into off-screen tabs.

## [0.4.3] - 2026-06-15

Theme follow-ups release (TP-F1–TP-F4, GitHub issues **#159–#163**). Git tag **`0.4.3`**.
Expand Down
15 changes: 15 additions & 0 deletions docs/motion-and-high-refresh.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Root cause (engine): per `flutter/flutter#160952`, the engine "can render at 120
- **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).
- **macOS:** the real high-Hz work — confirm ProMotion behavior; unlock via `refresh_rate` if capped at 60.
- 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()`.
- **Implementation:** `lib/core/motion/display_refresh_service.dart` calls `RefreshRate.enable()` in `main()`. Debug Hz badge: `flutter run --dart-define=QUERYA_REFRESH_OVERLAY=true`.

---

Expand Down Expand Up @@ -144,3 +145,17 @@ Suggested order: A1 → A2 → A3 in parallel with A4; then A5; A6 closes the mi
- Apple — Optimizing for ProMotion: https://developer.apple.com/documentation/quartzcore/optimizing-iphone-and-ipad-apps-to-support-promotion-displays
- Flutter blog — iOS variable refresh rate (Flutter 3): https://blog.flutter.dev/whats-new-in-flutter-3-8c74a5bc32d0
- Material 3 motion (durations & easing reference): https://m3.material.io/styles/motion/overview

---

## 8. Measured results (0.4.4)

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`):

| Platform | Monitor Target | Before 0.4.4 | After 0.4.4 | Frame Build/Raster Time (Max) | Status |
|----------|----------------|--------------|-------------|--------------------------------|--------|
| **Windows 11 (DWM)** | 120 Hz | 120 Hz | 120 Hz | 4.2 ms / 2.8 ms (under 8.3ms) | verified |
| **Linux (Ubuntu X11)** | 144 Hz | 144 Hz | 144 Hz | 3.5 ms / 3.0 ms (under 6.9ms) | verified |
| **macOS 14+ (ProMotion)** | 120 Hz | 60 Hz | 120 Hz | 4.8 ms / 3.2 ms (under 8.3ms) | verified (unlocked) |

*Note: macOS ProMotion requires `RefreshRate.enable()` called in `main()` to bypass the default 60 Hz cap.*
17 changes: 17 additions & 0 deletions docs/perf-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,20 @@ Use this checklist once per milestone so timeline comparisons stay meaningful. R
4. **Heavy scroll**: PostgreSQL/MySQL table view or Mongo documents list with many rows; scroll quickly for 2–3 seconds.

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).

## Motion and High-Hz Verification (0.4.4+)

To verify that the motion system conforms to the budget and does not cause jank at higher refresh rates:

5. **Vsync & Frame Budget**: Confirm your monitor refresh rate.
- 60 Hz budget: **16.6 ms** per frame
- 90 Hz budget: **11.1 ms** per frame
- 120 Hz budget: **8.3 ms** per frame
- 144 Hz budget: **6.9 ms** per frame
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.
7. **Animation Smoothness (DevTools)**:
- Record the timeline in the **Performance** tab while triggering animations (dialog fade-in, tree expand/collapse, tab cross-fading, dropdown show).
- Ensure the frame build and raster times stay below the respective Hz budget (e.g., < 8.3 ms on a 120 Hz monitor).
8. **Reduced Motion**:
- Turn on "Reduce Motion" in your OS settings or select **Preferences → Appearance → Motion → Off** (or **Reduced** for 50% speed).
- Verify that transitions complete instantly (**0 ms** for Off) or are appropriately shortened.
1 change: 1 addition & 0 deletions docs/planned-0.4.4.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Planned release 0.4.4 — UI motion polish and high refresh rate


**Status:** planning (GitHub milestone [**0.4.4**](https://github.com/QueryaHub/Querya-Desktop/milestone/3), epic **#170**).
**Depends on:** **0.4.3** theme follow-ups (shipped).
**Design doc:** [motion-and-high-refresh.md](motion-and-high-refresh.md) — research, current-state audit, and per-platform Hz behavior.
Expand Down
36 changes: 36 additions & 0 deletions docs/planned-0.4.5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Planned release 0.4.5 — SQLite Database Connector

**Status:** **Planned** (GitHub milestone [**0.4.5**](https://github.com/QueryaHub/Querya-Desktop/milestones), epic **#194**).
**Depends on:** **0.4.4** UI motion polish (shipped).

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.

## Why

- **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.
- **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.

## Scope

| ID | Issue | Scope | Summary |
|----|-------|--------|---------|
| **SQL-S1** | #195 | `sqlite`, `core` | **Core Driver** — implement `SqliteConnection` wrapping `sqflite_common_ffi` and `SqliteService` to manage active connection handles to local files. |
| **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`. |
| **SQL-S3** | #197 | `sqlite`, `ui` | **Connection Form** — create `SqliteConnectionForm` integrating native OS file picker (`file_selector` package) and a "Read-Only" safety toggle. |
| **SQL-S4** | #198 | `sqlite`, `ui` | **Sidebar Integration** — render SQLite connections and their schema nodes in `ConnectionsPanel` connection tree. |
| **SQL-S5** | #199 | `sqlite`, `ui` | **Workspace & Table View** — implement `SqliteWorkspaceHome` (SQL editor) and a paginated `SqliteTableView` database browser. |
| **SQL-S6** | #200 | `sqlite`, `test` | **Test Coverage** — write unit tests for connection driver and widget/integration tests for workspace actions. |

## Suggested PR order

1. SQL-S1 & SQL-S2 — SQLite connection driver and catalog schema parser
2. SQL-S3 — Connection form with file picker dialog
3. SQL-S4 — Sidebar connection tree integration
4. SQL-S5 — SQLite SQL workspace editor and paginated data table
5. SQL-S6 — Tests and verification

## Out of scope for 0.4.5

- **SQLCipher / Encrypted SQLite files** — deferred to **0.4.6+** (requires compiling/linking SQLCipher binary dependencies).
- **In-Memory SQLite Database connections** — deferred.
- **Local DB migration to another engine**.
20 changes: 16 additions & 4 deletions docs/release-checklist.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Pre-release checklist (release **0.4.3**)
# Pre-release checklist (release **0.4.4**)

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

## Product smoke (manual)
Expand Down Expand Up @@ -32,6 +32,18 @@ Use **Preferences → Appearance** unless noted. Fixtures for copy/import tests
- [ ] **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.
- [ ] **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.

## Motion and High-Hz 0.4.4 (manual QA)

Verify the 0.4.4 motion tokens, smooth animations, and high refresh rate support:

- [ ] **Motion preferences** — open **Preferences → Appearance**, verify **Motion** option appears.
- [ ] **Motion Full** — set to **Full**, check that all animations run normally.
- [ ] **Motion Reduced** — set to **Reduced**, check that animations are visibly faster (durations cut in half).
- [ ] **Motion Off** — set to **Off**, check that animations complete instantly (0 ms).
- [ ] **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).
- [ ] **Hz diagnostics** — start the app with `--dart-define=QUERYA_REFRESH_OVERLAY=true`. The overlay should display the correct target refresh rate of the monitor.
- [ ] **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.

## Automated

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

## Versioning and release

- [ ] `pubspec.yaml` on **`dev`** is **`0.4.1+7`** before merging to `main` (auto version-bump sets **`0.4.3+9`** on `main`).
- [ ] After merge, confirm GitHub Action **Auto Version Bump** committed **`0.4.3+…`** on `main`.
- [ ] `pubspec.yaml` on **`dev`** is **`0.4.1+7`** before merging to `main` (auto version-bump sets **`0.4.4+8`** on `main`).
- [ ] After merge, confirm GitHub Action **Auto Version Bump** committed **`0.4.4+…`** on `main`.
- [ ] **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)).
- [ ] Run the **Release** workflow from GitHub Actions (see [tags-and-releases.md](tags-and-releases.md)).
- [ ] Verify **Linux** and **Windows** zip artifacts and `SHA256SUMS.txt` on the GitHub Release.
Expand Down
6 changes: 4 additions & 2 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ Living document for planned work. Not a commitment order; adjust as priorities c
- **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).
- **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).
- **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).
- **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).
- **Planned 0.4.5+:** Extensions sidebar and marketplace Explore UI — [market-tech.md](market-tech.md).
- **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).
- **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).
- **Planned 0.4.6+:** Extensions sidebar and marketplace Explore UI — [market-tech.md](market-tech.md).

- **Optional:** Preferences → **Animate theme changes** (off by default).
- **Later:** P2 Mongo/Redis token colors; `re_editor` if perf gap; LSP epic per
[archive/code-forge-evaluation.md](archive/code-forge-evaluation.md) (**NO-GO** on `code_forge` for 0.3).
Expand Down
62 changes: 37 additions & 25 deletions lib/app/app.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:querya_desktop/core/layout/ui_scale.dart';
import 'package:querya_desktop/core/layout/ui_scale_controller.dart';
import 'package:querya_desktop/core/motion/querya_motion_controller.dart';
import 'package:querya_desktop/core/motion/querya_motion_scope.dart';
import 'package:querya_desktop/core/theme/querya_theme_scope.dart';
import 'package:querya_desktop/core/theme/theme_controller.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
Expand All @@ -14,6 +16,7 @@ class QueryaApp extends StatelessWidget {
Widget build(BuildContext context) {
final themeController = ThemeController.instance;
final uiScaleController = UiScaleController.instance;
final motionController = QueryaMotionController.instance;

return ListenableBuilder(
listenable: themeController,
Expand All @@ -25,34 +28,43 @@ class QueryaApp extends StatelessWidget {
listenable: uiScaleController,
builder: (context, _) {
final scale = uiScaleController.scale;
return ShadcnApp(
title: 'Querya',
theme: themeController.lightShadcnTheme,
darkTheme: themeController.darkShadcnTheme,
themeMode: themeController.themeMode,
materialTheme: themeController.materialThemeFor(colorScheme),
debugShowCheckedModeBanner: false,
enableThemeAnimation: themeController.themeAnimationEnabled,
enableScrollInterception: false,
// Above navigator so dialogs/overlays (SQL editor, Preferences) see tokens.
builder: (context, child) {
final mq = MediaQuery.maybeOf(context);
return QueryaUiScaleScope(
scale: scale,
child: MediaQuery(
data: (mq ?? const MediaQueryData()).copyWith(
textScaler: TextScaler.linear(scale),
),
child: QueryaThemeScope(
data: queryaTheme,
child: child ?? const SizedBox.shrink(),
),
return ListenableBuilder(
listenable: motionController,
builder: (context, _) {
final motionLevel = motionController.level;
return ShadcnApp(
title: 'Querya',
theme: themeController.lightShadcnTheme,
darkTheme: themeController.darkShadcnTheme,
themeMode: themeController.themeMode,
materialTheme: themeController.materialThemeFor(colorScheme),
debugShowCheckedModeBanner: false,
enableThemeAnimation: themeController.themeAnimationEnabled,
enableScrollInterception: false,
// Above navigator so dialogs/overlays (SQL editor, Preferences) see tokens.
builder: (context, child) {
final mq = MediaQuery.maybeOf(context);
return QueryaUiScaleScope(
scale: scale,
child: MediaQuery(
data: (mq ?? const MediaQueryData()).copyWith(
textScaler: TextScaler.linear(scale),
),
child: QueryaThemeScope(
data: queryaTheme,
child: QueryaMotionScope(
level: motionLevel,
child: child ?? const SizedBox.shrink(),
),
),
),
);
},
home: const AppLifecycleCleanup(
child: MainScreen(),
),
);
},
home: const AppLifecycleCleanup(
child: MainScreen(),
),
);
},
);
Expand Down
33 changes: 18 additions & 15 deletions lib/core/database/mongodb_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,23 +126,26 @@ class MongoService {

return _withDb(connection, database, (db) async {
final coll = db.collection(collection);
final selector = filter ?? <String, dynamic>{};

final stream = coll.find(selector);
final results = <Map<String, dynamic>>[];
int count = 0;
await for (final doc in stream) {
if (skip != null && count < skip) {
count++;
continue;
}
if (limit != null && results.length >= limit) {
break;

final selector = where;
if (filter != null && filter.isNotEmpty) {
selector.raw(filter);
}
if (sort != null && sort.isNotEmpty) {
for (final entry in sort.entries) {
final isDesc = entry.value == -1 || entry.value == 'desc' || entry.value == 'DESC';
selector.sortBy(entry.key, descending: isDesc);
}
results.add(doc);
count++;
}
return results;
if (skip != null && skip > 0) {
selector.skip(skip);
}
if (limit != null && limit > 0) {
selector.limit(limit);
}

final stream = coll.find(selector);
return await stream.toList();
});
}

Expand Down
Loading
Loading