native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Replace custom commands table with scrollable lazy stack

onevcat 22713fe3 c98dacd3

+83 -62
+83 -62
supacode/Features/Settings/Views/RepositorySettingsView.swift
··· 16 16 @State private var iconPickerCommandID: UserCustomCommand.ID? 17 17 @State private var iconPickerReturnResponder: NSResponder? 18 18 @State private var customCommandsFocusAnchor: NSView? 19 - @State private var customCommandsMeasuredRowHeight: CGFloat = 44 20 19 @State private var commandEditorCommandID: UserCustomCommand.ID? 21 20 @State private var editingNameCommandID: UserCustomCommand.ID? 22 21 @FocusState private var focusedNameEditorCommandID: UserCustomCommand.ID? ··· 308 307 @ViewBuilder 309 308 private var customCommandsEditor: some View { 310 309 VStack(alignment: .leading, spacing: 10) { 311 - Table(store.userSettings.customCommands, selection: $selectedCustomCommandID) { 312 - TableColumn("") { command in 313 - customCommandRowCell(commandID: command.id) { 314 - customCommandIconCell(command) 315 - } 316 - } 317 - .width(32) 318 - 319 - TableColumn("Name") { command in 320 - customCommandRowCell(commandID: command.id) { 321 - customCommandNameCell(command) 322 - } 323 - } 324 - 325 - TableColumn("Command") { command in 326 - customCommandRowCell(commandID: command.id) { 327 - customCommandCell(command) 328 - } 329 - } 330 - 331 - TableColumn("Shortcut") { command in 332 - customCommandRowCell(commandID: command.id) { 333 - customCommandShortcutCell(command) 310 + VStack(spacing: 0) { 311 + customCommandsHeaderRow 312 + Divider() 313 + ScrollView { 314 + LazyVStack(spacing: 4) { 315 + ForEach(store.userSettings.customCommands) { command in 316 + customCommandRow(command) 317 + .id(command.id) 318 + } 334 319 } 320 + .padding(.horizontal, 6) 321 + .padding(.vertical, 6) 335 322 } 323 + .frame(height: 300) 336 324 } 337 - .frame( 338 - minHeight: customCommandsTableHeight, 339 - idealHeight: customCommandsTableHeight, 340 - maxHeight: customCommandsTableHeight 341 - ) 342 - .onPreferenceChange(CustomCommandRowHeightPreferenceKey.self) { height in 343 - if height > 0 { 344 - customCommandsMeasuredRowHeight = height 345 - } 346 - } 325 + .clipShape(RoundedRectangle(cornerRadius: 8)) 347 326 348 327 HStack(spacing: 8) { 349 328 Button { ··· 564 543 return commands.last?.id 565 544 } 566 545 546 + private var customCommandsHeaderRow: some View { 547 + HStack(spacing: 8) { 548 + customCommandHeaderCell("", width: customCommandsIconColumnWidth, alignment: .center) 549 + customCommandHeaderCell("Name") 550 + customCommandHeaderCell("Command") 551 + customCommandHeaderCell("Shortcut", width: customCommandsShortcutColumnWidth) 552 + } 553 + .padding(.horizontal, 14) 554 + .padding(.vertical, 8) 555 + .font(.headline) 556 + .foregroundStyle(.secondary) 557 + } 558 + 559 + @ViewBuilder 560 + private func customCommandRow(_ command: UserCustomCommand) -> some View { 561 + let isSelected = selectedCustomCommandID == command.id 562 + HStack(spacing: 8) { 563 + customCommandRowCell(width: customCommandsIconColumnWidth, alignment: .center) { 564 + customCommandIconCell(command) 565 + } 566 + customCommandRowCell { 567 + customCommandNameCell(command) 568 + } 569 + customCommandRowCell { 570 + customCommandCell(command) 571 + } 572 + customCommandRowCell(width: customCommandsShortcutColumnWidth) { 573 + customCommandShortcutCell(command) 574 + } 575 + } 576 + .padding(.horizontal, 8) 577 + .padding(.vertical, 2) 578 + .background { 579 + RoundedRectangle(cornerRadius: 8) 580 + .fill(isSelected ? Color.accentColor.opacity(0.35) : .clear) 581 + } 582 + .contentShape(RoundedRectangle(cornerRadius: 8)) 583 + .onTapGesture { 584 + selectCustomCommand(command.id) 585 + } 586 + } 587 + 588 + @ViewBuilder 589 + private func customCommandHeaderCell( 590 + _ title: String, 591 + width: CGFloat? = nil, 592 + alignment: Alignment = .leading 593 + ) -> some View { 594 + if let width { 595 + Text(title) 596 + .frame(width: width, alignment: alignment) 597 + } else { 598 + Text(title) 599 + .frame(maxWidth: .infinity, alignment: alignment) 600 + } 601 + } 602 + 567 603 @ViewBuilder 568 604 private func customCommandRowCell<Content: View>( 569 - commandID: UserCustomCommand.ID, 605 + width: CGFloat? = nil, 606 + alignment: Alignment = .leading, 570 607 @ViewBuilder content: () -> Content 571 608 ) -> some View { 572 - content() 573 - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) 574 - .background { 575 - GeometryReader { proxy in 576 - Color.clear 577 - .preference(key: CustomCommandRowHeightPreferenceKey.self, value: proxy.size.height) 578 - } 579 - } 580 - .contentShape(Rectangle()) 581 - .onTapGesture { 582 - selectCustomCommand(commandID) 583 - } 609 + if let width { 610 + content() 611 + .frame(width: width, alignment: alignment) 612 + .frame(maxHeight: .infinity, alignment: alignment) 613 + } else { 614 + content() 615 + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: alignment) 616 + } 584 617 } 585 618 586 619 private func selectCustomCommand(_ commandID: UserCustomCommand.ID) { ··· 1104 1137 ) 1105 1138 } 1106 1139 1107 - private var customCommandsTableHeight: CGFloat { 1108 - let rowCount = CGFloat(store.userSettings.customCommands.count) 1109 - let rowHeight = max(customCommandsMeasuredRowHeight, 1) 1110 - let headerHeight: CGFloat = 32 1111 - let contentHeight = headerHeight + (rowCount * rowHeight) + 2 1112 - return max(220, contentHeight) 1113 - } 1140 + private var customCommandsIconColumnWidth: CGFloat { 48 } 1141 + 1142 + private var customCommandsShortcutColumnWidth: CGFloat { 180 } 1114 1143 } 1115 1144 1116 1145 private struct InlineEditableCellButton<Label: View>: View { ··· 1230 1259 private final class FirstResponderAnchorNSView: NSView { 1231 1260 override var acceptsFirstResponder: Bool { 1232 1261 true 1233 - } 1234 - } 1235 - 1236 - private struct CustomCommandRowHeightPreferenceKey: PreferenceKey { 1237 - static var defaultValue: CGFloat = 0 1238 - 1239 - static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { 1240 - value = max(value, nextValue()) 1241 1262 } 1242 1263 } 1243 1264