native macOS codings agent orchestrator
6
fork

Configure Feed

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

Measure row height from table cells for adaptive sizing

onevcat c98dacd3 e99f1d14

+14 -91
+14 -91
supacode/Features/Settings/Views/RepositorySettingsView.swift
··· 17 17 @State private var iconPickerReturnResponder: NSResponder? 18 18 @State private var customCommandsFocusAnchor: NSView? 19 19 @State private var customCommandsMeasuredRowHeight: CGFloat = 44 20 - @State private var customCommandsMeasuredHeaderHeight: CGFloat = 30 21 20 @State private var commandEditorCommandID: UserCustomCommand.ID? 22 21 @State private var editingNameCommandID: UserCustomCommand.ID? 23 22 @FocusState private var focusedNameEditorCommandID: UserCustomCommand.ID? ··· 340 339 idealHeight: customCommandsTableHeight, 341 340 maxHeight: customCommandsTableHeight 342 341 ) 343 - .background { 344 - TableMetricsProbe { metrics in 345 - customCommandsMeasuredRowHeight = metrics.rowHeight 346 - customCommandsMeasuredHeaderHeight = metrics.headerHeight 342 + .onPreferenceChange(CustomCommandRowHeightPreferenceKey.self) { height in 343 + if height > 0 { 344 + customCommandsMeasuredRowHeight = height 347 345 } 348 - .frame(width: 0, height: 0) 349 346 } 350 347 351 348 HStack(spacing: 8) { ··· 574 571 ) -> some View { 575 572 content() 576 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 + } 577 580 .contentShape(Rectangle()) 578 581 .onTapGesture { 579 582 selectCustomCommand(commandID) ··· 1104 1107 private var customCommandsTableHeight: CGFloat { 1105 1108 let rowCount = CGFloat(store.userSettings.customCommands.count) 1106 1109 let rowHeight = max(customCommandsMeasuredRowHeight, 1) 1107 - let headerHeight = max(customCommandsMeasuredHeaderHeight, 0) 1110 + let headerHeight: CGFloat = 32 1108 1111 let contentHeight = headerHeight + (rowCount * rowHeight) + 2 1109 1112 return max(220, contentHeight) 1110 1113 } ··· 1230 1233 } 1231 1234 } 1232 1235 1233 - private struct TableLayoutMetrics: Equatable { 1234 - let rowHeight: CGFloat 1235 - let headerHeight: CGFloat 1236 - } 1236 + private struct CustomCommandRowHeightPreferenceKey: PreferenceKey { 1237 + static var defaultValue: CGFloat = 0 1237 1238 1238 - private struct TableMetricsProbe: NSViewRepresentable { 1239 - let onResolve: (TableLayoutMetrics) -> Void 1240 - 1241 - func makeNSView(context: Context) -> TableMetricsProbeNSView { 1242 - let view = TableMetricsProbeNSView() 1243 - view.onResolve = onResolve 1244 - view.resolveSoon() 1245 - return view 1246 - } 1247 - 1248 - func updateNSView(_ nsView: TableMetricsProbeNSView, context: Context) { 1249 - nsView.onResolve = onResolve 1250 - nsView.resolveSoon() 1251 - } 1252 - } 1253 - 1254 - private final class TableMetricsProbeNSView: NSView { 1255 - var onResolve: ((TableLayoutMetrics) -> Void)? 1256 - private var lastMetrics: TableLayoutMetrics? 1257 - 1258 - override func viewDidMoveToWindow() { 1259 - super.viewDidMoveToWindow() 1260 - resolveSoon() 1261 - } 1262 - 1263 - override func viewDidMoveToSuperview() { 1264 - super.viewDidMoveToSuperview() 1265 - resolveSoon() 1266 - } 1267 - 1268 - func resolveSoon() { 1269 - DispatchQueue.main.async { [weak self] in 1270 - self?.resolve() 1271 - } 1272 - } 1273 - 1274 - private func resolve() { 1275 - guard let tableView = locateTableView() else { 1276 - return 1277 - } 1278 - let metrics = TableLayoutMetrics( 1279 - rowHeight: tableView.rowHeight + tableView.intercellSpacing.height, 1280 - headerHeight: tableView.headerView?.frame.height ?? 0 1281 - ) 1282 - guard metrics != lastMetrics else { 1283 - return 1284 - } 1285 - lastMetrics = metrics 1286 - onResolve?(metrics) 1287 - } 1288 - 1289 - private func locateTableView() -> NSTableView? { 1290 - if let table = firstTableView(in: self) { 1291 - return table 1292 - } 1293 - var current: NSView? = self 1294 - while let view = current { 1295 - if let table = firstTableView(in: view) { 1296 - return table 1297 - } 1298 - current = view.superview 1299 - } 1300 - return nil 1301 - } 1302 - 1303 - private func firstTableView(in view: NSView) -> NSTableView? { 1304 - if let table = view as? NSTableView { 1305 - return table 1306 - } 1307 - if let scrollView = view as? NSScrollView, 1308 - let table = scrollView.documentView as? NSTableView 1309 - { 1310 - return table 1311 - } 1312 - for subview in view.subviews { 1313 - if let table = firstTableView(in: subview) { 1314 - return table 1315 - } 1316 - } 1317 - return nil 1239 + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { 1240 + value = max(value, nextValue()) 1318 1241 } 1319 1242 } 1320 1243