Skip to content

Commit 6b7cf84

Browse files
committed
Refactoring: move LogStore into its own file
1 parent aed9803 commit 6b7cf84

File tree

2 files changed

+61
-59
lines changed

2 files changed

+61
-59
lines changed

Sources/LayoutInspector/DebugLayoutImpl.swift

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -186,62 +186,3 @@ struct ClearDebugLayoutLog: Layout {
186186
subviews[0].place(at: bounds.origin, proposal: proposal)
187187
}
188188
}
189-
190-
@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
191-
public final class LogStore: ObservableObject {
192-
@Published public var log: [LogEntry]
193-
var viewLabels: Set<String> = []
194-
195-
init(log: [LogEntry] = []) {
196-
self.log = log
197-
self.viewLabels = Set(log.map(\.label))
198-
}
199-
200-
func registerViewLabelAndWarnIfNotUnique(_ label: String, file: StaticString, line: UInt) {
201-
DispatchQueue.main.async { [self] in
202-
if viewLabels.contains(label) {
203-
let message: StaticString = "%@:%llu: Duplicate view label '%@' detected. Use unique labels in .layoutStep() calls"
204-
runtimeWarning(message, [String(describing: file), UInt64(line), label], file: file, line: line)
205-
}
206-
viewLabels.insert(label)
207-
}
208-
}
209-
210-
func logLayoutStep(_ label: String, step: LogEntry.Step) {
211-
DispatchQueue.main.async { [self] in
212-
guard let prevEntry = log.last else {
213-
// First log entry → start at indent 0.
214-
log.append(LogEntry(label: label, step: step, indent: 0))
215-
return
216-
}
217-
218-
var newEntry = LogEntry(label: label, step: step, indent: prevEntry.indent)
219-
let isSameView = prevEntry.label == label
220-
switch (isSameView, prevEntry.step, step) {
221-
case (true, .proposal(let prop), .response(let resp)):
222-
// Response follows immediately after proposal for the same view.
223-
// → We want to display them in a single row.
224-
// → Coalesce both layout steps.
225-
log.removeLast()
226-
newEntry = prevEntry
227-
newEntry.step = .proposalAndResponse(proposal: prop, response: resp)
228-
log.append(newEntry)
229-
230-
case (_, .proposal, .proposal):
231-
// A proposal follows a proposal → nested view → increment indent.
232-
newEntry.indent += 1
233-
log.append(newEntry)
234-
235-
case (_, .response, .response),
236-
(_, .proposalAndResponse, .response):
237-
// A response follows a response → last child returns to parent → decrement indent.
238-
newEntry.indent -= 1
239-
log.append(newEntry)
240-
241-
default:
242-
// Keep current indentation.
243-
log.append(newEntry)
244-
}
245-
}
246-
}
247-
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import Combine
2+
import Dispatch
3+
4+
@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
5+
public final class LogStore: ObservableObject {
6+
@Published public var log: [LogEntry]
7+
var viewLabels: Set<String> = []
8+
9+
init(log: [LogEntry] = []) {
10+
self.log = log
11+
self.viewLabels = Set(log.map(\.label))
12+
}
13+
14+
func registerViewLabelAndWarnIfNotUnique(_ label: String, file: StaticString, line: UInt) {
15+
DispatchQueue.main.async { [self] in
16+
if viewLabels.contains(label) {
17+
let message: StaticString = "%@:%llu: Duplicate view label '%@' detected. Use unique labels in .layoutStep() calls"
18+
runtimeWarning(message, [String(describing: file), UInt64(line), label], file: file, line: line)
19+
}
20+
viewLabels.insert(label)
21+
}
22+
}
23+
24+
func logLayoutStep(_ label: String, step: LogEntry.Step) {
25+
DispatchQueue.main.async { [self] in
26+
guard let prevEntry = log.last else {
27+
// First log entry → start at indent 0.
28+
log.append(LogEntry(label: label, step: step, indent: 0))
29+
return
30+
}
31+
32+
var newEntry = LogEntry(label: label, step: step, indent: prevEntry.indent)
33+
let isSameView = prevEntry.label == label
34+
switch (isSameView, prevEntry.step, step) {
35+
case (true, .proposal(let prop), .response(let resp)):
36+
// Response follows immediately after proposal for the same view.
37+
// → We want to display them in a single row.
38+
// → Coalesce both layout steps.
39+
log.removeLast()
40+
newEntry = prevEntry
41+
newEntry.step = .proposalAndResponse(proposal: prop, response: resp)
42+
log.append(newEntry)
43+
44+
case (_, .proposal, .proposal):
45+
// A proposal follows a proposal → nested view → increment indent.
46+
newEntry.indent += 1
47+
log.append(newEntry)
48+
49+
case (_, .response, .response),
50+
(_, .proposalAndResponse, .response):
51+
// A response follows a response → last child returns to parent → decrement indent.
52+
newEntry.indent -= 1
53+
log.append(newEntry)
54+
55+
default:
56+
// Keep current indentation.
57+
log.append(newEntry)
58+
}
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)