Skip to content

Commit 55f2850

Browse files
authored
polish(ios): empty state actions and VoiceOver custom actions for swipe-only deletes (#1180)
1 parent 8b17873 commit 55f2850

5 files changed

Lines changed: 27 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- iOS: VoiceOver "Delete row" / "Delete group" / "Delete tag" custom actions on rows whose only deletion path was a swipe gesture
13+
- iOS: empty Groups and Tags screens show a Create button so the action is reachable without opening the toolbar
14+
- iOS: "No Results" empty state in Query Editor explains the query returned no rows
1215
- iOS: iCloud sync runs every 30 minutes in the background via `BGAppRefreshTask` while the app is closed (gated by the iCloud Sync setting); iOS schedules the actual cadence based on usage and battery
1316
- iOS: Cmd+F focuses the search field in Tables and Data Browser (iPad keyboard canonical)
1417
- iOS: search text in Tables and Data Browser persists across process kill via `@SceneStorage` (per-window on iPad)

TableProMobile/TableProMobile/Views/DataBrowserView.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ struct DataBrowserView: View {
267267
.tint(.red)
268268
}
269269
}
270+
.accessibilityAction(named: Text("Delete row")) {
271+
guard !isView, viewModel.hasPrimaryKeys, !connection.safeModeLevel.blocksWrites else { return }
272+
deleteTarget = viewModel.primaryKeyValues(for: row)
273+
showDeleteConfirmation = true
274+
}
270275
}
271276

272277
@ViewBuilder

TableProMobile/TableProMobile/Views/GroupManagementView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct GroupManagementView: View {
4646
}
4747
.tint(.red)
4848
}
49+
.accessibilityAction(named: Text("Delete group")) {
50+
groupToDelete = group
51+
}
4952
}
5053
.onMove { source, destination in
5154
var sorted = appState.groups.sorted(by: { $0.sortOrder < $1.sortOrder })
@@ -62,6 +65,9 @@ struct GroupManagementView: View {
6265
Label("No Groups", systemImage: "folder")
6366
} description: {
6467
Text("Create a group to organize your connections.")
68+
} actions: {
69+
Button("Create Group") { showingAddGroup = true }
70+
.buttonStyle(.borderedProminent)
6571
}
6672
}
6773
}

TableProMobile/TableProMobile/Views/QueryEditorView.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,12 @@ struct QueryEditorView: View {
207207
}
208208
.frame(maxWidth: .infinity, maxHeight: .infinity)
209209
} else if viewModel.legacyRows.isEmpty {
210-
ContentUnavailableView("No Results", systemImage: "tray")
211-
.frame(maxWidth: .infinity, maxHeight: .infinity)
210+
ContentUnavailableView(
211+
"No Results",
212+
systemImage: "tray",
213+
description: Text("The query returned no rows.")
214+
)
215+
.frame(maxWidth: .infinity, maxHeight: .infinity)
212216
} else {
213217
resultList
214218
}

TableProMobile/TableProMobile/Views/TagManagementView.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ struct TagManagementView: View {
4747
}
4848
}
4949
}
50+
.accessibilityAction(named: Text("Delete tag")) {
51+
guard !tag.isPreset else { return }
52+
appState.deleteTag(tag.id)
53+
}
5054
}
5155
}
5256
.overlay {
@@ -55,6 +59,9 @@ struct TagManagementView: View {
5559
Label("No Tags", systemImage: "tag")
5660
} description: {
5761
Text("Create a tag to organize your connections.")
62+
} actions: {
63+
Button("Create Tag") { showingAddTag = true }
64+
.buttonStyle(.borderedProminent)
5865
}
5966
}
6067
}

0 commit comments

Comments
 (0)