git.iko.soy/parseable-macos
on master help sign in
Add text wrapping toggle to LiveTailView and QueryView (#33)

* Enable text wrapping in log table cells with dynamic row heights Remove the single-line constraint (.lineLimit(1)) from LogRowView cells so text wraps naturally within the column width. Change HStack alignment to .top and cell frame alignment to .topLeading so that cells with different content heights align properly at the top of each row. https://claude.ai/code/session_01SRni6yYp6GPxuKS3xfP3Ep * Add toggleable text wrapping for log table cells Add a wrap/unwrap button to both QueryView and LiveTailView toolbars that toggles between single-line truncated text and multi-line wrapped text in table cells. The setting is per-view and defaults to off (single-line, matching the previous behavior). https://claude.ai/code/session_01SRni6yYp6GPxuKS3xfP3Ep --------- Co-authored-by: Claude <noreply@anthropic.com>

commitfd052804ef6c102adbc22ed69a96ecdb5dd615fe authoriko <mail@iko.soy> dateSun 15 Feb 2026, 22:05 (8 months ago) parentc7e5d4e
3 files changed+26−3
ParseableViewer/Views/LiveTailView.swift+10 ParseableViewer/Views/LogTableView.swift+6−3 ParseableViewer/Views/QueryView.swift+10
ParseableViewer/Views/LiveTailView.swift+10
@@ -7,6 +7,7 @@ struct LiveTailView: View {
77 @State private var autoScroll = true
88 @State private var pulseOpacity: Double = 1.0
99 @State private var showColumnPopover = false
10+ @State private var wrapText = false
1011 @State private var sortColumn: String?
1112 @State private var sortAscending = false
1213 @State private var columnWidths: [String: CGFloat] = [:]
@@ -70,6 +71,14 @@ struct LiveTailView: View {
7071 .accessibilityLabel("Filter live tail entries")
7172 }
7273
74+ Button {
75+ wrapText.toggle()
76+ } label: {
77+ Image(systemName: wrapText ? "text.word.spacing" : "text.line.first.and.arrowtriangle.forward")
78+ }
79+ .help(wrapText ? "Disable text wrapping" : "Enable text wrapping")
80+ .accessibilityLabel(wrapText ? "Disable text wrapping" : "Enable text wrapping")
81+
7382 if !viewModel.columns.isEmpty {
7483 Button {
7584 showColumnPopover.toggle()
@@ -283,6 +292,7 @@ struct LiveTailView: View {
283292 columnWidths: columnWidths,
284293 isSelected: selectedRecord == sorted[index].record,
285294 isAlternate: index % 2 == 1,
295+ wrapText: wrapText,
286296 onCellFilter: { column, value, exclude in
287297 viewModel.addColumnFilter(column: column, value: value, exclude: exclude)
288298 }
ParseableViewer/Views/LogTableView.swift+6−3
@@ -149,6 +149,7 @@ struct LogTableView: View {
149149 let columns: [String]
150150 @Binding var selectedRecord: LogRecord?
151151 var isLoading: Bool = false
152+ var wrapText: Bool = false
152153 var onCellFilter: ((_ column: String, _ value: JSONValue?, _ exclude: Bool) -> Void)?
153154 var onMoveColumn: ((String, String) -> Void)?
154155 @State private var sortColumn: String?
@@ -188,6 +189,7 @@ struct LogTableView: View {
188189 columnWidths: columnWidths,
189190 isSelected: selectedIndex == index,
190191 isAlternate: index % 2 == 1,
192+ wrapText: wrapText,
191193 onCellFilter: onCellFilter
192194 )
193195 .onTapGesture {
@@ -529,18 +531,19 @@ struct LogRowView: View {
529531 let columnWidths: [String: CGFloat]
530532 let isSelected: Bool
531533 let isAlternate: Bool
534+ var wrapText: Bool = false
532535 var onCellFilter: ((_ column: String, _ value: JSONValue?, _ exclude: Bool) -> Void)?
533536
534537 var body: some View {
535− HStack(spacing: 0) {
538+ HStack(alignment: .top, spacing: 0) {
536539 ForEach(columns, id: \.self) { column in
537540 let value = record[column]
538541 Text(value?.displayString ?? "")
539542 .font(.system(.caption, design: .monospaced))
540− .lineLimit(1)
543+ .lineLimit(wrapText ? nil : 1)
541544 .padding(.horizontal, 6)
542545 .padding(.vertical, 3)
543− .frame(width: columnWidths[column] ?? 120, alignment: .leading)
546+ .frame(width: columnWidths[column] ?? 120, alignment: .topLeading)
544547 .foregroundStyle(colorForValue(column: column, value: value))
545548 .contextMenu {
546549 Button("Copy Value") {
ParseableViewer/Views/QueryView.swift+10
@@ -8,6 +8,7 @@ struct QueryView: View {
88 @State private var exportError: String?
99 @State private var showExportError = false
1010 @State private var showColumnPopover = false
11+ @State private var wrapText = false
1112
1213 var body: some View {
1314 @Bindable var vm = viewModel
@@ -192,6 +193,14 @@ struct QueryView: View {
192193
193194 Spacer()
194195
196+ Button {
197+ wrapText.toggle()
198+ } label: {
199+ Image(systemName: wrapText ? "text.word.spacing" : "text.line.first.and.arrowtriangle.forward")
200+ }
201+ .help(wrapText ? "Disable text wrapping" : "Enable text wrapping")
202+ .accessibilityLabel(wrapText ? "Disable text wrapping" : "Enable text wrapping")
203+
195204 if !viewModel.columns.isEmpty {
196205 Button {
197206 showColumnPopover.toggle()
@@ -223,6 +232,7 @@ struct QueryView: View {
223232 columns: viewModel.visibleColumns,
224233 selectedRecord: $vm.selectedLogEntry,
225234 isLoading: viewModel.isLoading,
235+ wrapText: wrapText,
226236 onCellFilter: { column, value, exclude in
227237 viewModel.addColumnFilter(column: column, value: value, exclude: exclude)
228238 Task {