Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file removed .github/screenshots/1.png
Binary file not shown.
Binary file removed .github/screenshots/10.png
Binary file not shown.
Binary file removed .github/screenshots/11.png
Binary file not shown.
Binary file removed .github/screenshots/12.png
Binary file not shown.
Binary file removed .github/screenshots/13.png
Binary file not shown.
Binary file removed .github/screenshots/14.png
Binary file not shown.
Binary file removed .github/screenshots/15.png
Binary file not shown.
Binary file removed .github/screenshots/2.png
Binary file not shown.
Binary file removed .github/screenshots/3.png
Binary file not shown.
Binary file removed .github/screenshots/4.png
Binary file not shown.
Binary file removed .github/screenshots/5.png
Binary file not shown.
Binary file removed .github/screenshots/6.png
Binary file not shown.
Binary file removed .github/screenshots/7.png
Binary file not shown.
Binary file removed .github/screenshots/8.png
Binary file not shown.
Binary file removed .github/screenshots/9.png
Binary file not shown.
21 changes: 15 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ cargo xtask lint # rustfmt and clippy, as CI runs them
cargo xtask e2e up # PostgreSQL, MySQL, MariaDB, ClickHouse and libSQL from docker-compose.yml
cargo xtask e2e # the suites that need them
cargo xtask e2e down
cargo xtask screenshots # the README screenshots, against the PostgreSQL above
cargo xtask docs-images # the landing page's images, from those screenshots
cargo xtask screenshots # the README's and landing page's screenshots, against the PostgreSQL above
cargo xtask demo-video # the demo video, against every engine above
cargo xtask docs-images # their smaller copies and link preview
```

`cargo xtask` is this repository's task runner (the `xtask/` crate); run it alone to list its commands. `COMPOSE="podman compose"` makes it use Podman.
Expand All @@ -43,16 +44,24 @@ CI (`.github/workflows/test.yml`) runs the Linux checks and the E2E suites, SQL

## Screenshots

`cargo xtask screenshots` takes the README's screenshots again, at 2048 Γ— 1152 points (4096 Γ— 2304 pixels on a Retina display). It restores `fixtures/screenshots/forum.sql` into the PostgreSQL from `docker-compose.yml`, starts from the connections, tabs and settings in `fixtures/screenshots/data`, and plays the scenes in `crates/barsql-ui/src/screenshots.rs` in a snapshot build. A BarSQL window stays open while they run. It finishes with `cargo xtask docs-images`, which writes each screenshot into `docs/screenshots` as a full-size lossless WebP plus 640, 800 and 1280px copies, which the landing page picks from to fit the screen.
`cargo xtask screenshots` takes the screenshots again. It restores `fixtures/screenshots/forum.sql` into the PostgreSQL from `docker-compose.yml`, starts from the connections, tabs and settings in `fixtures/screenshots/data`, and plays the scenes in `crates/barsql-ui/src/screenshots.rs` in a snapshot build. The window is 1920 Γ— 1080 points and stays hidden: each shot renders offscreen at the display's scale and is scaled to 1920 Γ— 1080 pixels, so a Retina Mac and a 125% Windows display give the same size. Windows still needs a display at least that many points across, since it keeps even a hidden window within it. Each is kept as a lossless WebP in `docs/screenshots`, which the README and the landing page share. It finishes with `cargo xtask docs-images`, which makes the 640, 800 and 1280px copies, the link preview and the README's video poster.

For a single screenshot, build with `cargo build -p barsql --features snapshot`, then point `BARSQL_SNAPSHOT=out.png` at a data folder in `BARSQL_DATA_DIR`. The app draws its window headless, saves it and quits. `BARSQL_SNAPSHOT_SIZE` sets the window's size in points (`2048x1152`), `BARSQL_SNAPSHOT_RUN=1` runs the active tab first, and `BARSQL_SNAPSHOT_PANEL` chooses what the screenshot shows:
For a single screenshot, build with `cargo build -p barsql --features snapshot`, then point `BARSQL_SNAPSHOT=out.png` at a data folder in `BARSQL_DATA_DIR`. The app draws its window headless, saves it and quits. `BARSQL_SNAPSHOT_SIZE` sets the window's size in points (`1920x1080`), `BARSQL_SNAPSHOT_RUN=1` runs the active tab first, and `BARSQL_SNAPSHOT_PANEL` chooses what the screenshot shows:

- the sidebar panels: `saved`, `recent`, `connections`
- the grid: `cell`, `export`, `json`
- dialogs: `connection-dialog`, `import`, `about`, `shortcuts`, `tips`
- the update dialog: `update`, `update-current`, `update-downloading`, `update-ready`, `update-failed`
- other screens: `plan`, `quick`, `quick=<query>`, `suggest=<text>`, `toasts`, `palette` (the command palette), `chart` (the first result as a chart, with `BARSQL_SNAPSHOT_RUN=1`), `er` (the `main` schema's ER diagram), `structure` (a table's Structure tab: the first in `main`, or `structure=<table>`)

## Demo video

`cargo xtask demo-video` records the two-minute demo into `target/demo-video/BarSQL-demo.mp4` (1080p, 30 fps, H.264) and copies it to `docs/demo.mp4`, which the landing page plays. It needs [ffmpeg](https://ffmpeg.org) (`brew install ffmpeg`, `winget install ffmpeg`, or `FFMPEG` pointing at one) and starts PostgreSQL, MySQL, ClickHouse, libSQL and SQL Server from `docker-compose.yml`, which stay up afterwards. The forum database gets a `staging` schema to compare against and a trigger for the schema tree to show, both from `fixtures/demo-video/staging.sql`, and the other engines get a sample table each, created off camera.

The tour itself is `crates/barsql-ui/src/screenshots/video.rs`, in the screenshots' hidden 1920 Γ— 1080 point window at zoom 15, with a drawn pointer, typing at a human pace and a caption for each step. It opens on the editor of a forum connection saved off camera, and adds the MySQL connection on camera before the six engines. The camera skips loads and crossfades over changes made off camera. Every frame is rendered offscreen; only the frames that changed are saved, as PNGs in `target/demo-video/frames` with an ffconcat list of how long each shows, which ffmpeg turns into the video. Change a caption or a step there and run it again; a run takes about 20 minutes, mostly recording.

The README plays a GitHub upload of the video, as GitHub plays only its own uploads there. After a new recording, drag `docs/demo.mp4` into the README in GitHub's editor and replace the old upload's link with the new one.

## Translations

BarSQL speaks English, Deutsch, Π‘ΡŠΠ»Π³Π°Ρ€ΡΠΊΠΈ and EspaΓ±ol. A new language is mostly JSON and needs little of the rest of the code; [#25](https://github.com/Bare7a/BarSQL/pull/25) added Spanish and touches every step below.
Expand Down Expand Up @@ -85,7 +94,7 @@ python3 -m http.server 8765 --directory docs # then open http://localhost:8765
## Project Structure

```text
β”œβ”€β”€ .github/ # test and release workflows, PR and issue templates, the README screenshots
β”œβ”€β”€ .github/ # test and release workflows, PR and issue templates
β”œβ”€β”€ Cargo.toml # the workspace; GPUI Kit pinned to an exact version
β”œβ”€β”€ rust-toolchain.toml # the Rust version rustup installs
β”œβ”€β”€ docker-compose.yml # PostgreSQL / MySQL / MariaDB / ClickHouse / libSQL / SQL Server for the E2E suites
Expand All @@ -99,7 +108,7 @@ python3 -m http.server 8765 --directory docs # then open http://localhost:8765
β”‚ β”œβ”€β”€ barsql-storage/ # the JSON files in BarSQL-data
β”‚ └── barsql-ui/ # the GPUI views, locales and whole-window scenarios
β”œβ”€β”€ xtask/ # cargo xtask: lint, e2e, screenshots, docs-images, icons, package, bump-version
β”œβ”€β”€ docs/ # the landing page at barsql.bare7a.eu (GitHub Pages)
β”œβ”€β”€ docs/ # the landing page at barsql.bare7a.eu (GitHub Pages) and the README's images
β”œβ”€β”€ guide/ # the user guide, one page per area
β”œβ”€β”€ fixtures/
β”‚ β”œβ”€β”€ golden/ # per-engine expectations for the E2E suites
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "3"
members = ["crates/*", "xtask"]

[workspace.package]
version = "1.2.6"
version = "1.2.7"
edition = "2024"
license = "GPL-3.0-only"
publish = false
Expand Down
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
No cloud. No accounts. No telemetry.
Just a focused, native desktop tool for **PostgreSQL**, **MySQL / MariaDB**, **SQL Server**, **ClickHouse**, **Turso / libSQL** and **SQLite**, on Windows, macOS and Linux.

🌐 **[barsql.bare7a.eu](https://barsql.bare7a.eu)** Β· πŸ“– **[User Guide](guide/README.md)**
🌐 **[barsql.bare7a.eu](https://barsql.bare7a.eu)** Β· 🎬 **[Demo video](https://barsql.bare7a.eu/demo.mp4)** Β· πŸ“– **[User Guide](guide/README.md)**

![BarSQL's editor with schema-aware suggestions, a saved query's results in the grid and the focused row as JSON](.github/screenshots/1.png?raw=true)
https://github.com/user-attachments/assets/ea4b7bd3-82b9-469b-b99c-4619aeb6e83a

---

Expand Down Expand Up @@ -88,29 +88,29 @@ Work with **SQLite**, **PostgreSQL**, **MySQL / MariaDB**, **SQL Server**, **Cli

<table>
<tr>
<td align="center"><img src=".github/screenshots/1.png?raw=true" width="100%"><br><sub><b>Editor</b></sub></td>
<td align="center"><img src=".github/screenshots/2.png?raw=true" width="100%"><br><sub><b>Transactions & multiple results</b></sub></td>
<td align="center"><img src=".github/screenshots/3.png?raw=true" width="100%"><br><sub><b>Table data</b></sub></td>
<td align="center"><a href="docs/screenshots/1.webp"><img src="docs/screenshots/1-800.webp" width="100%"></a><br><sub><b>Editor</b></sub></td>
<td align="center"><a href="docs/screenshots/2.webp"><img src="docs/screenshots/2-800.webp" width="100%"></a><br><sub><b>Transactions & multiple results</b></sub></td>
<td align="center"><a href="docs/screenshots/3.webp"><img src="docs/screenshots/3-800.webp" width="100%"></a><br><sub><b>Table data</b></sub></td>
</tr>
<tr>
<td align="center"><img src=".github/screenshots/4.png?raw=true" width="100%"><br><sub><b>Cell editor</b></sub></td>
<td align="center"><img src=".github/screenshots/5.png?raw=true" width="100%"><br><sub><b>Grid</b></sub></td>
<td align="center"><img src=".github/screenshots/6.png?raw=true" width="100%"><br><sub><b>Export</b></sub></td>
<td align="center"><a href="docs/screenshots/4.webp"><img src="docs/screenshots/4-800.webp" width="100%"></a><br><sub><b>Cell editor</b></sub></td>
<td align="center"><a href="docs/screenshots/5.webp"><img src="docs/screenshots/5-800.webp" width="100%"></a><br><sub><b>Grid</b></sub></td>
<td align="center"><a href="docs/screenshots/6.webp"><img src="docs/screenshots/6-800.webp" width="100%"></a><br><sub><b>Export</b></sub></td>
</tr>
<tr>
<td align="center"><img src=".github/screenshots/7.png?raw=true" width="100%"><br><sub><b>Connections</b></sub></td>
<td align="center"><img src=".github/screenshots/8.png?raw=true" width="100%"><br><sub><b>Quick Search</b></sub></td>
<td align="center"><img src=".github/screenshots/9.png?raw=true" width="100%"><br><sub><b>DDL viewer</b></sub></td>
<td align="center"><a href="docs/screenshots/7.webp"><img src="docs/screenshots/7-800.webp" width="100%"></a><br><sub><b>Connections</b></sub></td>
<td align="center"><a href="docs/screenshots/8.webp"><img src="docs/screenshots/8-800.webp" width="100%"></a><br><sub><b>Quick Search</b></sub></td>
<td align="center"><a href="docs/screenshots/9.webp"><img src="docs/screenshots/9-800.webp" width="100%"></a><br><sub><b>DDL viewer</b></sub></td>
</tr>
<tr>
<td align="center"><img src=".github/screenshots/10.png?raw=true" width="100%"><br><sub><b>Plan viewer</b></sub></td>
<td align="center"><img src=".github/screenshots/11.png?raw=true" width="100%"><br><sub><b>CSV & SQL import</b></sub></td>
<td align="center"><img src=".github/screenshots/12.png?raw=true" width="100%"><br><sub><b>Structure editor</b></sub></td>
<td align="center"><a href="docs/screenshots/10.webp"><img src="docs/screenshots/10-800.webp" width="100%"></a><br><sub><b>Plan viewer</b></sub></td>
<td align="center"><a href="docs/screenshots/11.webp"><img src="docs/screenshots/11-800.webp" width="100%"></a><br><sub><b>CSV & SQL import</b></sub></td>
<td align="center"><a href="docs/screenshots/12.webp"><img src="docs/screenshots/12-800.webp" width="100%"></a><br><sub><b>Structure editor</b></sub></td>
</tr>
<tr>
<td align="center"><img src=".github/screenshots/13.png?raw=true" width="100%"><br><sub><b>ER diagram</b></sub></td>
<td align="center"><img src=".github/screenshots/14.png?raw=true" width="100%"><br><sub><b>Quick charts</b></sub></td>
<td align="center"><img src=".github/screenshots/15.png?raw=true" width="100%"><br><sub><b>Appearance</b></sub></td>
<td align="center"><a href="docs/screenshots/13.webp"><img src="docs/screenshots/13-800.webp" width="100%"></a><br><sub><b>ER diagram</b></sub></td>
<td align="center"><a href="docs/screenshots/14.webp"><img src="docs/screenshots/14-800.webp" width="100%"></a><br><sub><b>Quick charts</b></sub></td>
<td align="center"><a href="docs/screenshots/15.webp"><img src="docs/screenshots/15-800.webp" width="100%"></a><br><sub><b>Appearance</b></sub></td>
</tr>
</table>

Expand Down
2 changes: 0 additions & 2 deletions crates/barsql-ui/locales/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,10 @@
"search": "НамСри Ρ‚Π°Π±Π»ΠΈΡ†Π°",
"matches": "{{index}} ΠΎΡ‚ {{count}}",
"noMatches": "Няма Ρ‚Π°ΠΊΠ°Π²Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°",
"keysOnly": "Π‘Π°ΠΌΠΎ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅",
"keysOnlyTooltip": "ПокаТи само ΠΊΠ»ΡŽΡ‡ΠΎΠ²ΠΈΡ‚Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΈ",
"zoomIn": "Π£Π²Π΅Π»ΠΈΡ‡ΠΈ",
"zoomOut": "Намали",
"zoomReset": "ΠžΠ±Ρ€Π°Ρ‚Π½ΠΎ Π½Π° 100%",
"fit": "ΠŸΠΎΠ±Π΅Ρ€ΠΈ",
"fitTooltip": "ПокаТи цялата Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠ°",
"open": "ΠžΡ‚Π²ΠΎΡ€ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°"
},
Expand Down
2 changes: 0 additions & 2 deletions crates/barsql-ui/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,10 @@
"search": "Tabelle suchen",
"matches": "{{index}} von {{count}}",
"noMatches": "Keine Tabelle passt",
"keysOnly": "Nur SchlΓΌssel",
"keysOnlyTooltip": "Nur die SchlΓΌsselspalten zeigen",
"zoomIn": "Vergrâßern",
"zoomOut": "Verkleinern",
"zoomReset": "ZurΓΌck auf 100 %",
"fit": "Einpassen",
"fitTooltip": "Das ganze Diagramm zeigen",
"open": "Tabelle ΓΆffnen"
},
Expand Down
2 changes: 0 additions & 2 deletions crates/barsql-ui/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,10 @@
"search": "Find a table",
"matches": "{{index}} of {{count}}",
"noMatches": "No table matches",
"keysOnly": "Keys only",
"keysOnlyTooltip": "Show only the key columns",
"zoomIn": "Zoom in",
"zoomOut": "Zoom out",
"zoomReset": "Back to 100%",
"fit": "Fit",
"fitTooltip": "Show the whole diagram",
"open": "Open table"
},
Expand Down
2 changes: 0 additions & 2 deletions crates/barsql-ui/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -447,12 +447,10 @@
"search": "Buscar una tabla",
"matches": "{{index}} de {{count}}",
"noMatches": "Ninguna tabla coincide",
"keysOnly": "Solo claves",
"keysOnlyTooltip": "Mostrar solo las columnas clave",
"zoomIn": "Acercar",
"zoomOut": "Alejar",
"zoomReset": "Volver al 100 %",
"fit": "Ajustar",
"fitTooltip": "Mostrar todo el diagrama",
"open": "Abrir la tabla"
},
Expand Down
31 changes: 17 additions & 14 deletions crates/barsql-ui/src/connection_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,15 @@ impl ConnectionForm {
cx: &mut Context<Self>,
) -> Div {
v_flex()
.child(form::checkbox(id, checked, t(cx, label), false, cx).debug_selector(move || id.into()).on_click(
cx.listener(move |form, _, _, cx| {
flip(form);
cx.notify();
}),
))
.child(
form::checkbox(id, checked, t(cx, label), false, cx)
.debug_selector(move || id.into())
.on_click(cx.listener(move |form, _, _, cx| {
flip(form);
cx.notify();
}))
.test_support(),
)
.child(form::hint(t(cx, hint), cx).pl(rems(2.)))
}

Expand Down Expand Up @@ -643,14 +646,14 @@ fn database_items(mut menu: PopupMenu, databases: &[String], form: &Entity<Conne
menu.scrollable(true)
}

// Last opened dialog, for the scenario tests.
#[cfg(all(test, feature = "e2e"))]
// Last opened dialog, for the scenario tests and the demo video.
#[cfg(any(all(test, feature = "e2e"), feature = "snapshot"))]
pub(crate) struct Opened(pub WeakEntity<ConnectionForm>);

#[cfg(all(test, feature = "e2e"))]
#[cfg(any(all(test, feature = "e2e"), feature = "snapshot"))]
impl Global for Opened {}

#[cfg(all(test, feature = "e2e"))]
#[cfg(any(all(test, feature = "e2e"), feature = "snapshot"))]
impl ConnectionForm {
pub(crate) fn databases(&self) -> Option<&[String]> {
self.databases.as_ref().map(|(_, databases)| databases.as_slice())
Expand All @@ -668,9 +671,9 @@ enum Browse {
KnownHosts,
}

// Gives scenario tests a selector to click into.
fn labelled(selector: &'static str, input: Input) -> Div {
div().debug_selector(move || selector.into()).child(input)
// A selector for scenario tests and a scope for test lookups.
fn labelled(selector: &'static str, input: Input) -> Stateful<Div> {
div().id(selector).debug_selector(move || selector.into()).child(input)
}

impl Render for ConnectionForm {
Expand Down Expand Up @@ -1147,7 +1150,7 @@ pub fn open(
let editing = !config.id.is_empty();
let on_saved: OnSaved = Rc::new(on_saved);
let form = cx.new(|cx| ConnectionForm::new(config, on_saved, window, cx));
#[cfg(all(test, feature = "e2e"))]
#[cfg(any(all(test, feature = "e2e"), feature = "snapshot"))]
cx.set_global(Opened(form.downgrade()));
let handle = form.clone();
let name = form.read(cx).fields.name.clone();
Expand Down
Loading
Loading