Improved progress display

Previously, the progress bar updated only after completing an entire table.

For large tables such as LIBARC, this could make the application appear to have stopped responding.

Phase 10 updates the interface while rows are being exported.
This commit is contained in:
Mark Gregory
2026-10-17 11:54:29 +01:00
parent e1a9b4037e
commit d441aea02c
8 changed files with 33 additions and 59 deletions
-11
View File
@@ -1,11 +0,0 @@
# Phase 30 — Server Counters graphs fix
- Adds a dedicated **Server Counters** item under **Administration → Management**.
- Retrieves all actual server counters using `SHOW GLOBAL STATUS` (not `SHOW GLOBAL VARIABLES`).
- Places nine colour-coded Swift Charts above the counters, directly on the Server Counters screen.
- Graphs show current thread counts and per-second rates for cumulative counters.
- Counter cards remain visible beneath the charts; the filter field filters the cards.
- Samples are collected every five seconds when Auto-refresh is enabled. The first rate point requires two successful samples.
- Existing dashboard, SQL editor and schema editor are preserved.
This release was not compiled on macOS or tested against a live MySQL server.
-7
View File
@@ -1,7 +0,0 @@
# Phase 31 — Server Counters Layout
- Server counter cards appear first, with a compact responsive grid.
- Live graphs appear directly below the counter cards in the same scroll view.
- Bytes counters are displayed in readable units; uptime in days/hours/minutes; numeric counters use separators.
- Existing graph collection, automatic refresh and schema editing are retained.
- Requires macOS/Xcode compilation and live MySQL verification.
-8
View File
@@ -1,8 +0,0 @@
# Phase 32 — Administration View Restoration
- Server Counters: inline coloured graphs followed by the complete searchable MySQL status grid (no omitted counters).
- Server Status: full SHOW GLOBAL STATUS data restored below the performance overview, with search.
- Status and System Variables: restored original native table/grid presentation; no inappropriate charts or counter tiles.
- Connection Statistics and InnoDB: retain graphs and complete tabular results.
- No MySQL mutations; monitoring remains read-only.
- Xcode build and live MySQL validation must be performed on macOS.
-1
View File
@@ -1 +0,0 @@
Phase 33: Server Counters fixed split layout. Nine real MySQL sample charts pinned in horizontal scroll strip above independently scrolling full coloured SHOW GLOBAL STATUS table. All counters retained. Auto-refresh does not blank existing data. No Xcode build performed.
+22 -32
View File
@@ -4155,7 +4155,7 @@ private struct WorkbenchInlinePerformanceDashboard: View {
Text("\(samples.count) samples · refreshes every 5 seconds")
.font(.caption).foregroundStyle(.secondary)
}
LazyVGrid(columns: [GridItem(.adaptive(minimum: 360), spacing: 14)], spacing: 12) {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 410), spacing: 16)], spacing: 12) {
panel("Queries per second", metric: "Queries", rate: true, tint: .blue)
panel("Active connections", metric: "Threads_connected", rate: false, tint: .teal)
panel("Running threads", metric: "Threads_running", rate: false, tint: .orange)
@@ -4204,44 +4204,34 @@ private struct WorkbenchServerCountersScreen: View {
category == "All" ? rows : rows.filter { $0.count >= 2 && group($0[0]) == category }
}
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 18) {
HStack {
Label("Server overview", systemImage: "server.rack").font(.title3.bold())
Spacer()
Text("Live MySQL status · 5-second refresh").font(.caption).foregroundStyle(.secondary)
}
LazyVGrid(columns: [GridItem(.adaptive(minimum: 155), spacing: 10)], spacing: 10) {
overview("Queries", metric: "Queries", tint: .blue)
overview("Connected", metric: "Threads_connected", tint: .teal)
overview("Running", metric: "Threads_running", tint: .orange)
overview("Slow queries", metric: "Slow_queries", tint: .red)
overview("Received", metric: "Bytes_received", tint: .purple)
overview("Sent", metric: "Bytes_sent", tint: .green)
}
HStack {
Label("Performance trends", systemImage: "chart.xyaxis.line").font(.title3.bold())
Spacer()
Text("\(samples.count) samples").font(.caption).foregroundStyle(.secondary)
}
ScrollView(.vertical) {
VStack(alignment: .leading, spacing: 20) {
// Graphs are the primary content, never hidden below summary cards.
WorkbenchCounterCharts(page: .serverCounters, samples: samples)
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
HStack {
Label("All server counters", systemImage: "list.bullet.rectangle").font(.title3.bold())
Label("All MySQL server counters", systemImage: "list.bullet.rectangle")
.font(.title3.bold())
Spacer()
Text("\(visibleRows.count) of \(rows.count)").font(.caption).foregroundStyle(.secondary)
Text("\(visibleRows.count) of \(rows.count) counters")
.font(.caption).foregroundStyle(.secondary)
}
Picker("Counter category", selection: $category) {
ForEach(categories, id: \.self) { Text($0).tag($0) }
}
.pickerStyle(.segmented)
WorkbenchColouredCounterTable(columns: ["Variable_name", "Value"], rows: visibleRows)
.frame(minHeight: 360, idealHeight: 600)
Text("Colours identify counter families, not server health. Error totals are cumulative; a nonzero value does not by itself indicate a current fault.")
.frame(height: 450)
Text("Colours identify counter families, not server health. Error totals are cumulative; nonzero values do not necessarily indicate a current fault.")
.font(.caption).foregroundStyle(.secondary)
}
.padding(18)
.padding(20)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
// MARK: - Phase 29: Inline coloured counter graphs
@@ -4449,15 +4439,15 @@ private struct WorkbenchCounterCharts: View {
.foregroundStyle(tint).lineStyle(StrokeStyle(lineWidth: 2.5))
}
.chartYAxis { AxisMarks(position: .leading) }
.frame(height: 115)
.frame(height: 205)
if values.isEmpty {
Text("Waiting for samples").font(.caption2).foregroundStyle(.secondary)
}
}
.padding(14)
.padding(16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(tint.opacity(0.08))
.clipShape(RoundedRectangle(cornerRadius: 12))
.background(Color(nsColor: .controlBackgroundColor), in: RoundedRectangle(cornerRadius: 12))
.overlay(RoundedRectangle(cornerRadius: 12).stroke(tint.opacity(0.35), lineWidth: 1))
}
var body: some View {
@@ -4469,10 +4459,10 @@ private struct WorkbenchCounterCharts: View {
Text("\(samples.count) samples · 5-second refresh")
.font(.caption).foregroundStyle(.secondary)
}
LazyVGrid(columns: [GridItem(.adaptive(minimum: 360), spacing: 14)], spacing: 12) {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 410), spacing: 16)], spacing: 12) {
ForEach(metrics, id: \.self) { metric in graph(metric) }
}
Text("Graphs use real MySQL samples. Cumulative counters display change per second; thread counts show current values. Rates appear after two successful samples.")
Text("Live MySQL data • refreshes every five seconds. Rates appear after two successful samples; thread counts show current values.")
.font(.caption).foregroundStyle(.secondary)
}
}
+11
View File
@@ -0,0 +1,11 @@
# Phase 37 — Server Counters Graphs First
Based on the exact Xcode project supplied in Archive(20261017-104400).zip.
- Server Counters opens with the large performance graphs as the first content, with no overview cards pushing them down.
- Responsive two-column grid at typical desktop widths; each chart is 205 points tall.
- Coloured chart lines and filled areas, subtle matching chart borders, current readings, time and value axes.
- Full searchable server counter list remains below the graphs, grouped by category.
- Existing icon resources, Server Status, Status and System Variables, and schema editor preserved.
Note: source-only change; requires Xcode compilation and live MySQL verification on macOS.