From 93974ded3297cbecb6f3b265e9df9f694101de03 Mon Sep 17 00:00:00 2001 From: xuhengyu Date: Wed, 17 Jun 2026 17:34:04 +0800 Subject: [PATCH 1/2] feat(datagrid): add Add button to status bar to insert a new row --- CHANGELOG.md | 1 + .../Main/Child/MainEditorContentView.swift | 3 ++- .../Views/Main/Child/MainStatusBarView.swift | 24 +++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9a84c58..2e143ff1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Traditional Chinese (繁體中文) language in Settings > General with full UI translation +- An Add button in the table status bar inserts a new row at the end of the grid and starts editing it. ## [0.51.1] - 2026-06-16 diff --git a/TablePro/Views/Main/Child/MainEditorContentView.swift b/TablePro/Views/Main/Child/MainEditorContentView.swift index 7684bcb72..cfac91a48 100644 --- a/TablePro/Views/Main/Child/MainEditorContentView.swift +++ b/TablePro/Views/Main/Child/MainEditorContentView.swift @@ -714,7 +714,8 @@ struct MainEditorContentView: View { onRemove: { coordinator.structureActions?.removeRow?() } ), onToggleFilters: { coordinator.toggleFilterPanel() }, - onFetchAll: { coordinator.fetchAllRows() } + onFetchAll: { coordinator.fetchAllRows() }, + onAddRow: currentTabAllowsAddRow ? { onAddRow() } : nil ) } diff --git a/TablePro/Views/Main/Child/MainStatusBarView.swift b/TablePro/Views/Main/Child/MainStatusBarView.swift index f7bdf369e..296824cdf 100644 --- a/TablePro/Views/Main/Child/MainStatusBarView.swift +++ b/TablePro/Views/Main/Child/MainStatusBarView.swift @@ -41,6 +41,7 @@ struct MainStatusBarView: View { let structureState: StatusBarStructureState let onToggleFilters: () -> Void let onFetchAll: (() -> Void)? + let onAddRow: (() -> Void)? @State private var showColumnPopover = false @@ -56,6 +57,15 @@ struct MainStatusBarView: View { return "\(label) (\(combo.displayString))" } + private var addRowHelp: String { + let label = String(localized: "Add Row") + guard let combo = AppSettingsManager.shared.keyboard.shortcut(for: .addRow), + !combo.isCleared else { + return label + } + return "\(label) (\(combo.displayString))" + } + private var columnsAccessibilityLabel: String { guard !columnState.hidden.isEmpty else { return String(localized: "Columns") @@ -141,6 +151,20 @@ struct MainStatusBarView: View { } if showsDataChrome { + if let onAddRow { + Button { + onAddRow() + } label: { + HStack(spacing: 4) { + Image(systemName: "plus") + Text("Add") + } + } + .controlSize(.small) + .help(addRowHelp) + .accessibilityLabel(String(localized: "Add Row")) + } + if snapshot.hasColumns { Button { showColumnPopover.toggle() From 335806bbbc63625b59cd2564baa65a629cf07fd2 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Wed, 17 Jun 2026 17:07:10 +0700 Subject: [PATCH 2/2] fix(datagrid): hide status-bar Add button outside Data mode and fix test init --- .../Views/Main/Child/MainStatusBarView.swift | 20 ++++++++++--------- .../Views/Main/MainStatusBarLayoutTests.swift | 17 +++++++++++++++- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/TablePro/Views/Main/Child/MainStatusBarView.swift b/TablePro/Views/Main/Child/MainStatusBarView.swift index 296824cdf..bcd976109 100644 --- a/TablePro/Views/Main/Child/MainStatusBarView.swift +++ b/TablePro/Views/Main/Child/MainStatusBarView.swift @@ -48,18 +48,20 @@ struct MainStatusBarView: View { private var isStructureMode: Bool { viewMode == .structure } private var showsDataChrome: Bool { !isStructureMode } + static func showsAddRow(viewMode: ResultsViewMode, canAddRow: Bool) -> Bool { + viewMode == .data && canAddRow + } + private var filterToggleHelp: String { - let label = String(localized: "Toggle Filters") - guard let combo = AppSettingsManager.shared.keyboard.shortcut(for: .toggleFilters), - !combo.isCleared else { - return label - } - return "\(label) (\(combo.displayString))" + helpText(String(localized: "Toggle Filters"), shortcut: .toggleFilters) } private var addRowHelp: String { - let label = String(localized: "Add Row") - guard let combo = AppSettingsManager.shared.keyboard.shortcut(for: .addRow), + helpText(String(localized: "Add Row"), shortcut: .addRow) + } + + private func helpText(_ label: String, shortcut action: ShortcutAction) -> String { + guard let combo = AppSettingsManager.shared.keyboard.shortcut(for: action), !combo.isCleared else { return label } @@ -151,7 +153,7 @@ struct MainStatusBarView: View { } if showsDataChrome { - if let onAddRow { + if Self.showsAddRow(viewMode: viewMode, canAddRow: onAddRow != nil), let onAddRow { Button { onAddRow() } label: { diff --git a/TableProTests/Views/Main/MainStatusBarLayoutTests.swift b/TableProTests/Views/Main/MainStatusBarLayoutTests.swift index 2887daa17..057c55045 100644 --- a/TableProTests/Views/Main/MainStatusBarLayoutTests.swift +++ b/TableProTests/Views/Main/MainStatusBarLayoutTests.swift @@ -42,8 +42,23 @@ struct MainStatusBarLayoutTests { onRemove: {} ), onToggleFilters: {}, - onFetchAll: nil + onFetchAll: nil, + onAddRow: nil ) #expect(type(of: view.body) != Never.self) } + + @Test("Add Row button shows only in Data mode when adding is allowed") + func addRowVisibilityByMode() { + #expect(MainStatusBarView.showsAddRow(viewMode: .data, canAddRow: true)) + #expect(!MainStatusBarView.showsAddRow(viewMode: .structure, canAddRow: true)) + #expect(!MainStatusBarView.showsAddRow(viewMode: .json, canAddRow: true)) + } + + @Test("Add Row button is hidden when adding is not allowed") + func addRowHiddenWhenNotAllowed() { + #expect(!MainStatusBarView.showsAddRow(viewMode: .data, canAddRow: false)) + #expect(!MainStatusBarView.showsAddRow(viewMode: .structure, canAddRow: false)) + #expect(!MainStatusBarView.showsAddRow(viewMode: .json, canAddRow: false)) + } }