diff --git a/.changeset/stability-json-search-1-2.md b/.changeset/stability-json-search-1-2.md
new file mode 100644
index 00000000..34127a71
--- /dev/null
+++ b/.changeset/stability-json-search-1-2.md
@@ -0,0 +1,32 @@
+### New Features
+
+#### Data Table
+- Search highlighting: the toolbar search now shows exactly where each match falls — matched text is highlighted inside the visible cells, across every column
+- JSON tree view in expanded rows: fold and unfold any nested object or array with proper chevrons, type-colored values, and item/key counts — plus per-field **Copy value** and **Open in JSON viewer** actions that jump straight into the full Monaco viewer. A Tree/Raw toggle is remembered across sessions
+
+### Bug Fixes
+
+#### Stability
+- Fixed the app freezing when opening tables with very large cells — multi-MB file buffers stored in `jsonb`/`text`/blob columns could lock up the whole app. Cells above 256 KB now load as a truncated preview with the real size shown; the grid, JSON viewer, copy, and export all mark the truncation clearly, and editing or filtering on a truncated cell is blocked so a preview can never be saved back over real data. Applies to PostgreSQL, MySQL, SQLite, and the built-in MCP server
+- A crash inside one table view can no longer take down the whole app: rendering and interaction errors are contained to that tab, which shows a "Reload this view" card while every other tab, the sidebar, and the status bar keep working
+- SQLite: large blobs no longer render as unbounded hex text (the worst case doubled the data size on screen)
+
+#### Database Switcher
+- The search box is now always there and focused the moment the switcher opens — start typing immediately, with any number of databases
+- New shortcuts: **⌘D** opens the database switcher, **⇧⌘C** the connection switcher; arrows, Tab, and Enter drive the list right from the search box
+
+#### Sidebar
+- Restored smooth scrolling to the bottom of large table lists: removed the inline column-expansion rows that broke the virtualized list
+- "View data structure" is now "View structure"
+
+#### Licensing
+- Active trials always keep Pro access: only a definitive "trial expired" verdict locks Pro features — a transient license-check failure can no longer lock out trial or paid users
+
+### Changes
+
+#### AI Chat
+- The conversation column now matches the composer width for a comfortable reading measure, with more breathing room between messages
+
+#### Performance
+- Sorting SQL results by JSON columns no longer re-stringifies every cell on every comparison
+- Copy and export of object cells reuse one serialization path and stay fast on large result sets
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 55d720e0..1ac1370f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -405,9 +405,10 @@ jobs:
TAG: ${{ env.RELEASE_TAG }}
run: gh release upload "$TAG" --repo "$RELEASES_REPO" latest.json --clobber
-# ── 4. Refresh the Scoop manifest in the public releases repo ────────────────
-# Scoop clones the bucket repo anonymously, so the manifest must live in
-# RELEASES_REPO, not in this private source repo.
+# ── 4. Refresh the Scoop manifest + changelog in the public releases repo ────
+# Scoop clones the bucket repo anonymously, and the website reads the
+# changelog from the public repo — both must live in RELEASES_REPO, not
+# in this private source repo.
update-scoop:
needs: build
runs-on: ubuntu-latest
@@ -468,6 +469,26 @@ jobs:
git push origin HEAD
fi
+ # Mirror the changelog into the public repo so the website (and anyone
+ # browsing github.com/broisnischal/stroke) sees release history without
+ # access to the private source repo. Fetched at the release tag so it
+ # includes the entry auto-release just folded in.
+ - name: Sync CHANGELOG.md
+ env:
+ GH_TOKEN: ${{ secrets.RELEASES_TOKEN }}
+ TAG: ${{ env.RELEASE_TAG }}
+ run: |
+ gh api "repos/${{ github.repository }}/contents/CHANGELOG.md?ref=${TAG}" \
+ --jq .content | base64 -d > CHANGELOG.md
+
+ git add CHANGELOG.md
+ if git diff --cached --quiet; then
+ echo "Changelog already current."
+ else
+ git commit -m "docs(changelog): stroke ${TAG}"
+ git push origin HEAD
+ fi
+
# Optional instant Homebrew tap refresh. Without a PAT this is skipped and
# the tap updates itself on its own schedule instead (see homebrew-tap repo).
# (secrets can't be used in an `if:`, so the check lives in the script.)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5fd6eb1..95068693 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,17 +6,48 @@ All notable changes to Stroke are listed here, newest first.
## [1.1.0] - 2026-07-03
-### Changes
-- feat:: working on improvement, better sql editor, a11y, new releases and more, (#15)
+### New Features
+#### Tabs
+- Pin tabs: pinned tabs stay grouped at the front, show a pin badge, and survive "Close Others" / "Close All"
-## [1.0.0] - 2026-07-01
+#### Themes
+- New **Graphite** theme, wired through the editor and diagram themes
+
+#### Licensing
+- New in-app license page: "Activate Pro" now opens a dedicated tab with key entry, plan status, what Pro unlocks, and a purchase link — confetti included on activation
+- License entry in Settings with a live plan badge (Pro / Trial / Free)
+
+#### SQL Editor
+- Column sorting on query results — numbers sort numerically, NULLs last, and the sorted order carries into the JSON view, charts, and CSV/JSON exports
+
+### Bug Fixes
+
+#### Data Table
+- Pinned columns now freeze flush to the left edge — no more empty gutter-wide gap after scrolling
+- Query results grid is read-only: removed actions that can't apply to ad-hoc results (Filter/Exclude by value, Edit, Set NULL, Duplicate/Delete row, INSERT copy)
+- Column stats no longer error with "Invalid identifier" on SQL editor results
+- Sidebar rows no longer shift as row counts load in
+
+#### Window
+- Double-clicking the titlebar now maximizes reliably (a duplicate handler was maximizing and instantly restoring)
### Changes
-- feat:: perf, ux, themes and optimizations (#13)
+#### Performance
+- Reconnect feels instant: the overlay drops as soon as the connection is live, and schemas/tables stream into the sidebar instead of blocking the screen
+- Table row counts load lazily — the sidebar renders immediately with placeholders and exact counts fill in from a background pass; schema switches get the same speedup
+- Faster Postgres connect: one fewer round trip per pooled connection, and the reachability check runs concurrently with the real handshake
+- AI streaming responses parse markdown at most once per frame instead of once per token
+
+#### Settings
+- Settings dialog redesigned: grouped sections (Appearance / Behavior / More), clearer hierarchy, keyboard-shortcut chips
-## [Unreleased]
+#### Release pipeline
+- Releases now publish to the public `stroke` repository — auto-update, Homebrew, and Scoop keep working with the private source repo
+
+
+## [1.0.0] - 2026-07-01
### Performance
- Faster (re)connect: `onConnected` now loads query history + MCP autostart concurrently with the schema/table load instead of behind it, and no longer double-fetches the query stores on startup.
diff --git a/src-tauri/src/db/mysql.rs b/src-tauri/src/db/mysql.rs
index dd3a70cf..218d19a9 100644
--- a/src-tauri/src/db/mysql.rs
+++ b/src-tauri/src/db/mysql.rs
@@ -39,10 +39,26 @@ pub fn cell_to_json(row: &sqlx::mysql::MySqlRow, idx: usize) -> Value {
return v.map(|t| json!(t.to_string())).unwrap_or(Value::Null);
}
if let Ok(v) = row.try_get::