Skip to content

chore(release): Querya Desktop 0.4.19 - #1483

Merged
ZhuchkaTriplesix merged 767 commits into
mainfrom
release/0.4.19
Oct 11, 2026
Merged

ZhuchkaTriplesix merged 767 commits into
mainfrom
release/0.4.19

Conversation

@ZhuchkaTriplesix

Copy link
Copy Markdown
Member

Release 0.4.19, cut from dev (ea74feb2). GitFlow: this merges into main; after the tag, main goes back into dev.

What is in the branch

  • pubspec.yaml 0.4.19+2: the same as main after the auto-bump that followed 0.4.18, so the merge has no version conflict. The auto-bump after this merge gives 0.4.20+3.
  • packaging/linux/aur/PKGBUILD pkgver=0.4.19 (also as on main).
  • CHANGELOG.md: [Unreleased] is now ## [0.4.19] - 2026-10-11 (CI copies it into the GitHub Release; scripts/extract-changelog-section.sh 0.4.19 finds it), a new [Unreleased] keeps the Planned items.
  • docs/release-checklist.md: 0.4.19 product smoke (buttons and controls, dialog footers, toast, light theme, run modes, SQL toolbar, ER diagram, connections, PostgreSQL TLS, startup recovery, MCP, packaging), versioning and docs steps.
  • docs/roadmap.md: 0.4.18 shipped, 0.4.19 is this cut, 0.5.0 next.
  • Flatpak metainfo.xml: 0.4.19 release entry.

Highlights (full text in the changelog)

NoSQL workbench, SSH tunnelling and Production safeguards, ER diagram (groups, notes, saved views, DBML / PDF), read-only MCP server, SQL run modes and one-row toolbar, UI kit (one control scale, QueryaButton family, own toast and text styles), PostgreSQL TLS and extension sandbox fixes, performance work on the grid, editor and drivers.

Before tagging

  1. The manual smoke list in docs/release-checklist.md on a release build.
  2. CI green on this PR.
  3. Tag 0.4.19 on the merge commit that contains 0.4.19+2 (not on the auto-bump commit), then the Release workflow.
  4. After the release: the release zip's URL and sha256 in packaging/linux/flatpak/com.queryahub.querya_desktop.flathub.yml.

Not in this release

The Flathub submission (flathub/flathub#10606) still has lint errors (HTTPS on queryahub.com or another app id, --filesystem=home, an EOL GNOME runtime) and the manifest installs the Flutter bundle in a layout that will not start; it is tracked separately.

ZhuchkaTriplesix and others added 30 commits October 10, 2026 16:09
feat(erd): a new group gathers its tables when its frame would cover other cards
…iews menu, grouping hint, marked cards

- A note without a colour is a slightly darker sheet with a shadow, on
  screen and in the exports, not the canvas colour with a hairline.
- Touching a note, its resize handle or a group title gives the keyboard
  back to the canvas, so Esc, zoom and search keys work.
- Every row of the views menu has a mark, so the labels line up; long view
  names are cut in the menu and the toolbar.
- A card's New group... entry says that Shift+click marks more tables.
- A marked card gets a ring outside it instead of a thicker border, so its
  content keeps the width it was measured for.
fix(erd): interface review polish (notes, keys, views menu, grouping hint, marks)
…ySQL and SQLite pools (#1306)

acquire counted the lease before reconnecting a dropped entry. When the
reconnect threw, nobody held the lease to release it, so the entry
stayed in use for good: never idle-disposed, never evicted, and a few of
them filled the pool with pool exhausted errors.

The count is now given back when the reconnect fails.
…ved secrets (#1302)

The edit forms never show stored secrets, and the test built a connection
with id 0 and the blank fields, so a correct saved password failed with
Authentication failed. Blank password, URI password and SSH fields now
mean the saved ones, as they do on Save; Test SSH connection too.

Tunnels clear the secrets they are given after the login. The tests now
hand them a copy, so a successful test no longer empties the form's own
SSH secrets before Save.
…le-flight connect (#1307)

- The TCP and TLS connect take a timeout (10 s, as PostgreSQL and MySQL),
  and so does AUTH / PING, so an unresponsive host no longer holds the
  caller for the OS timeout.
- A failed attempt closes its socket; before, every wrong password left
  one open.
- Concurrent connect() calls share one attempt: one socket, one tunnel.
fix(db): a failed reconnect gives its lease back in the pools (#1306)
…ger throws (#1302)

injectUriPasswordIfMissing put the password into the userinfo raw, and
Uri.replace rejects an '@', '/' or '#' there with a FormatException: the
Test Connection and Save of an edited URI connection failed for such a
password. It is percent-encoded now.
#1303)

The secure-store reads swallowed every failure and returned nulls, so a
locked keyring or a missing secret service was reported as
Authentication failed, and a following edit could save the missing
password as empty.

- readForConnection / readSshSecretsForConnection throw
  SecretsStoreUnavailableException when the store does not answer; an
  absent secret is still null.
- The drivers let it through instead of connecting without a password,
  and the error text names the keyring, not the credentials.
- Editing a connection stops before any write when the saved secrets
  cannot be read, and says so.
…mer (#1307)

Socket.connect with a timeout creates a timer; widget tests that open a
Redis view and end with the connect pending failed on it. The default
limit is a test seam (zero: no limit) set by flutter_test_config; tests
of the limit pass their own.
dartssh2 passes the verify callback the OpenSSH fingerprint
(SHA256:<base64>) as UTF-8 text. formatFingerprint hashed those bytes
again, so the fingerprint shown by Test SSH connection was a hash of a
hash, and a value from ssh-keygen -lf never matched a pin.

- formatFingerprint returns SHA256:<base64> as OpenSSH prints it.
- A pin matches in that form (any prefix case, with or without padding,
  or the bare base64). Pins saved before this change (the 64-digit hex
  the app used to show) still match.
- The fake SSH server presents what dartssh2 does, so the tests no longer
  hide the difference.
…ntication failure (#1305)

SshAuthenticationException's text contains 'authentication failed', which
the mapper turned into AuthFailed with the database hint and dropped the
host. A wrong bastion password read as a wrong database password.

- The mapper handles SshAuthenticationException, SshHostKeyMismatchException
  and the new SshConnectionException before any text matching, keeping the
  host and user and pointing at the SSH tunnel settings.
- openTunnel tells a rejected login (SSHAuthError) from a transport or
  protocol failure, which is no longer 'SSH authentication failed', and the
  transport and jump host failures name the host and port.
- describeDatabaseError keeps the hint of a mapped error.
- Redis, MySQL and MongoDB testConnection return the reason, in the same
  mapped words as PostgreSQL (Authentication failed..., Cannot reach...),
  not a bare bool.
- Every form showed 'Connection failed' for any result that did not start
  with 'error:', so the reason PostgreSQL and SQLite returned was dropped
  too. connectionTestMessage shows it, and a reason stays on screen for
  20 s instead of 5.
- The SQLite form's 'error:' text lost its first letter (substring(7)).
PostgreSQL words a missing INSERT/UPDATE column as
column "x" of relation "t" does not exist; the relation pattern
matched it and the user read Table "t" does not exist for a table that
exists. Missing columns (PostgreSQL, MySQL, SQLite) are their own error,
checked before the table patterns.
…ed-secrets

fix(connections): Test Connection of an edited connection uses the saved secrets (#1302)
fix(redis): connect timeout, no socket left after a failed AUTH, single-flight connect (#1307)
…rors

fix(storage): an unreadable keyring is an error, not an empty password (#1303)
fix(ssh): host key fingerprints are in the OpenSSH format (#1304)
mongodb://h1:27017,h2:27017/db?replicaSet=rs0 is valid MongoDB, but Dart's
Uri reads the host list as a port: the URL import said Invalid URL/URI
format, and connecting, opening another database and tunnelling threw
FormatException.

- MongoUri splits a MongoDB string without Uri.parse and is used for the
  database name, the per-database URI, the TLS parameters and the tunnel
  target.
- Through an SSH tunnel the string becomes the one local endpoint with
  directConnection=true; a mongodb+srv:// string cannot be tunnelled and
  says so.
- The URL import reads the first seed and keeps the whole string; the
  certificate paths of a host-list string are found.
…1313)

forceClose returned before releasing the SSH tunnel when there was no
connection object yet, and the attempt it overtook finished as a
connected session. An attempt now notes the generation it started in;
when disconnect or forceClose bumped it, the attempt closes what it
opened, releases its tunnel and fails, and a connect after a forceClose
starts a new attempt instead of joining the overtaken one.
…er explains why nothing opens (#1314)

promptEditConnection returned null without a word when the extension was
not installed, and fell back to the first driver of a manifest when none
matched the connection's type, opening another driver's form.

- A missing extension, a driver the extension no longer provides, and an
  unknown connection type each show a toast saying what is missing.
- The driver is the one of the row's type, or the only one the extension
  has; never another of several.
…what they are (#1316)

- A full pool is a PoolExhaustedException (the session count and what to
  do), not Bad state: ...
- Connection reset / broken pipe / terminating connection / server gone
  away on an established session is ConnectionLostException with a
  reconnect hint, not did not accept the connection.
- HandshakeException and certificate / TLS-version failures are
  TlsFailureException pointing at the SSL mode and root certificate.
…ows SQLite, IPv6 (#1315)

- A password with @, /, # or ? written as is no longer ends in
  'Invalid URL/URI format.': the user info up to the last @ is
  percent-encoded and the stored string is the valid one. When it still
  cannot be read, the message names percent-encoding.
- sqlite:///C:/data/app.db is C:/data/app.db, without the URI's slash.
- An IPv6 host is bracketed in the default name and in the Mongo URI the
  connection builds.
… tunnel, a failed save restores them all (#1311)

- An edit form has Remove the saved password; a blank field still keeps
  it. Test Connection honours it.
- Saving a connection without a tunnel removes its SSH password, key and
  passphrase from the keyring instead of leaving them there.
- A failed secret write restores the SSH secrets too (they are written
  key by key), not only the password and connection string.
fix(mongodb): connection strings with several hosts work (#1309)
fix(errors): a missing column is not reported as a missing table (#1310)
…nect

fix(mysql): forceClose and disconnect during connect end the attempt (#1313)
…ction

fix(connections): editing a connection of a missing extension or driver explains why nothing opens (#1314)
ZhuchkaTriplesix and others added 27 commits October 11, 2026 15:56
…yaDialogActions

About, Driver manager and Preferences build their footer with
QueryaDialogActions (one divider, lg, spacing 8). Close in the update
dialog's up-to-date state and in the extension manager header is ghost
instead of primary: a dismiss-only action is never the main one.

Refs #1441
fix(ui): rules use the workbench border colour through QueryaDivider
The ERD toolbar was md buttons next to a dense (28 px) detail strip, and
the chart toolbar mixed a dense strip with lg dropdowns. Each toolbar now
says its size once (ERD md, chart and results sm) and its controls follow.

Refs #1439
fix(ui): the new-connection wizard search is a QueryaSearchField
ERD group / note / view name, New folder and Create database build a
Cancel + primary footer by hand (12 px gap, own divider). They now use
QueryaDialogActions: order, spacing 8, lg, one divider, Esc cancels.

Refs #1441
…l-roles

fix(ui): dismiss-only dialogs use a ghost Close in QueryaDialogActions
PostgreSQL, MySQL, SQLite, Redis, MongoDB and extension connection forms
build Test connection + Cancel + Save by hand. They now use
QueryaDialogActions: Cancel, Test connection, Save in the standard
order, spacing 8, one divider, Esc cancels.

Refs #1441
fix(ui): toolbar rows set one control size through QueryaControlScope
refactor(ui): name dialogs use QueryaDialogActions for their footer
…oters

refactor(ui): connection forms use QueryaDialogActions for their footer
…iminate 3x memory copies and string allocations (#1355) (#1464)
* refactor(ui): app toast on our own overlay, off shadcn

showAppToast draws its toasts in one root overlay entry: fade and slide
in over QueryaMotion.standard (instant under reduced motion), stacking
upwards, closing after showDuration or through a close button. Removes
app_toast.dart from the shadcn allow-list.

Refs #1365 #1465

* fix(ui): toast lifetime on a timer, works from the navigator's own context

The toast ended on a ticker, so pumpAndSettle ran its whole 5 s; it now
plays only the entry on the controller and ends on a timer, as the old
shadcn toast did. showAppToast also finds the overlay through the root
navigator when the context is the navigator itself, and does nothing
when there is none.
… hidden (#1468)

* refactor(ui): text styles from our own QueryaTextStyles, shadcn TextExtension hidden

xSmall / small / base / large / medium / semiBold / bold / muted /
foreground are a kit extension over DefaultTextStyle with the sizes the
app already used. The widgets.dart barrel and every direct shadcn import
hide shadcn's TextExtension, so call sites are unchanged.

Refs #1465

* fix(ui): hide TextExtension on prefixed shadcn imports, add ellipsis()

An extension from a prefixed import still applies implicitly, so the 27
files importing shadcn as shadcn saw both extensions and every chained
modifier was ambiguous. They now hide it too. QueryaTextStyles also gets
ellipsis() (one line, cut), which one call site used.

* style: child last in QueryaTextStyles calls (sort_child_properties_last)
)

The row had no hand-written sizes and happened to be md; it is now inside
a QueryaControlScope(md) and a test measures the run split button, the
explain button, the editor icon buttons and the session menu at 32 px.

Refs #1439
…1471)

* refactor(ui): QueryaIconButton is a thin wrapper over QueryaButton

One icon-button system: same states, ring and semantics as every other
button, no Material InkWell path. The color / activeColor parameters go;
the call sites that used a colour as a toggled look pass isActive.

Refs #1440

* fix(ui): an active destructive button is tinted with the destructive colour

* test(ui): measure the icon button with loose constraints
* refactor(erd): the export flows move out of ErdView into ErdExporter

ErdExporter holds Mermaid, DBML, SVG, PNG and PDF export and the export
palette setting; ErdView implements ErdExportSource to give it its data,
colours and the canvas boundary. erd_view.dart: 1784 -> ~1590 lines.

Refs #1362

* fix(erd): exporter toasts check the context after awaits, DBML test uses quoted names
…ds land (#1476)

* refactor(ui): the Mongo and staging private buttons are kit buttons

_ActionButton (databases, collections), _SmallActionButton, _TreeIconButton
and the staging toolbar's _ToolbarButton are QueryaButton / QueryaIconButton
with a tooltip; five hand-drawn button classes less.

Refs #1445

* refactor(ui): raw Material buttons and literal tooltip delays leave lib, guards land

14 Material IconButtons (password eyes, dismiss, close, delete, sidebar
toggle, search clear), the value panel's TextButton / ElevatedButton and
literal tooltip delays use the kit. test/guards/button_standard_guards_test.dart
forbids shadcn buttons, raw Material buttons, *Button classes outside the
kit (two allowed) and literal tooltip delays.

Refs #1445 #1339

* style: const kit icon buttons (prefer_const_constructors)

* test: the value panel's update button is a QueryaButton
…llows the active tab (#1481)

Run / Explain with nothing to run show 'Nothing to run' instead of
silence. The status bar shows the active tab's own message, row and column
counts and time, and nothing for a tab that has not run. A plain 'N row(s).'
is no longer repeated in the status bar (the result bar and the counts on its
right already show it).

Fixes #1478, fixes #1479
…lbar row (#1482)

* fix(ui): disabled primary is a grey chip, tx badge, MCP button sizes, ERD toolbar, switch row inset

- A disabled filled button uses the muted surface and label instead of a
  half-transparent accent.
- The SQL toolbar badge reads Auto-commit / Manual commit before the first
  run instead of 'Transaction —'.
- MCP section buttons are md like the rest of Preferences.
- Switch rows no longer inset their label by 4 px.
- Below 1100 px the ERD toolbar's Note, Auto layout and hidden-tables
  buttons are icon-only, so Export does not wrap alone.

Refs #1480

* test(e2e): before the first run the badge reads Auto-commit
- pubspec 0.4.19+2 (as on main after the 0.4.18 bump), AUR pkgver 0.4.19
- CHANGELOG: [Unreleased] becomes [0.4.19] - 2026-10-11 with what was merged
  since the last update; a new [Unreleased] keeps the planned items
- release checklist: 0.4.19 product smoke, versioning and docs steps
- roadmap: 0.4.18 shipped, 0.4.19 is this cut
- Flatpak metainfo: 0.4.19 release entry
@ZhuchkaTriplesix
ZhuchkaTriplesix merged commit 4247ab7 into main Oct 11, 2026
15 checks passed
@ZhuchkaTriplesix
ZhuchkaTriplesix deleted the release/0.4.19 branch October 11, 2026 15:03
Comment thread .devcontainer/Dockerfile
COPY --from=docker:27-cli /usr/local/bin/docker /usr/local/bin/docker
COPY --from=docker:27-cli /usr/local/libexec/docker/cli-plugins/docker-compose /usr/local/libexec/docker/cli-plugins/docker-compose

ENV DISPLAY=:99

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Магическое число и переменная

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants