native macOS codings agent orchestrator
6
fork

Configure Feed

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

Use measured NSTableView metrics for adaptive table height

onevcat e99f1d14 b6cfd5a9

+102 -3
+102 -3
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 + @State private var customCommandsMeasuredHeaderHeight: CGFloat = 30 19 21 @State private var commandEditorCommandID: UserCustomCommand.ID? 20 22 @State private var editingNameCommandID: UserCustomCommand.ID? 21 23 @FocusState private var focusedNameEditorCommandID: UserCustomCommand.ID? ··· 338 340 idealHeight: customCommandsTableHeight, 339 341 maxHeight: customCommandsTableHeight 340 342 ) 343 + .background { 344 + TableMetricsProbe { metrics in 345 + customCommandsMeasuredRowHeight = metrics.rowHeight 346 + customCommandsMeasuredHeaderHeight = metrics.headerHeight 347 + } 348 + .frame(width: 0, height: 0) 349 + } 341 350 342 351 HStack(spacing: 8) { 343 352 Button { ··· 1093 1102 } 1094 1103 1095 1104 private var customCommandsTableHeight: CGFloat { 1096 - let rowHeight: CGFloat = 44 1097 - let headerHeight: CGFloat = 30 1098 - return max(220, headerHeight + (CGFloat(store.userSettings.customCommands.count) * rowHeight)) 1105 + let rowCount = CGFloat(store.userSettings.customCommands.count) 1106 + let rowHeight = max(customCommandsMeasuredRowHeight, 1) 1107 + let headerHeight = max(customCommandsMeasuredHeaderHeight, 0) 1108 + let contentHeight = headerHeight + (rowCount * rowHeight) + 2 1109 + return max(220, contentHeight) 1099 1110 } 1100 1111 } 1101 1112 ··· 1216 1227 private final class FirstResponderAnchorNSView: NSView { 1217 1228 override var acceptsFirstResponder: Bool { 1218 1229 true 1230 + } 1231 + } 1232 + 1233 + private struct TableLayoutMetrics: Equatable { 1234 + let rowHeight: CGFloat 1235 + let headerHeight: CGFloat 1236 + } 1237 + 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 1219 1318 } 1220 1319 } 1221 1320