Fix log pause not freezing display

Snapshot log list when paused so new logs don't displace old entries.
Search and level filter still work against the snapshot.
This commit is contained in:
世界
2026-03-06 10:09:56 +08:00
parent a1ac77e08f
commit 0636b47d36
+35 -10
View File
@@ -18,6 +18,8 @@ public class LogDataModel: ObservableObject {
private let commandClient: CommandClient private let commandClient: CommandClient
private weak var viewModel: LogViewModel? private weak var viewModel: LogViewModel?
private var pausedLogSnapshot: [LogEntry]?
private var lastPaused = false
private var lastProcessedLogCount = 0 private var lastProcessedLogCount = 0
private var lastEffectiveLevel: Int? private var lastEffectiveLevel: Int?
private var lastSearchText = "" private var lastSearchText = ""
@@ -48,38 +50,59 @@ public class LogDataModel: ObservableObject {
let debouncedSearchText = viewModel.$searchText let debouncedSearchText = viewModel.$searchText
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main) .debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
Publishers.CombineLatest4( Publishers.CombineLatest(
commandClient.$logList, Publishers.CombineLatest4(
commandClient.$defaultLogLevel, commandClient.$logList,
viewModel.$selectedLogLevel, commandClient.$defaultLogLevel,
debouncedSearchText viewModel.$selectedLogLevel,
debouncedSearchText
),
viewModel.$isPaused
) )
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] logList, defaultLogLevel, selectedLogLevel, searchText in .sink { [weak self] combined, isPaused in
guard let self else { return } guard let self else { return }
let (logList, defaultLogLevel, selectedLogLevel, searchText) = combined
let effectiveLevel = selectedLogLevel ?? defaultLogLevel let effectiveLevel = selectedLogLevel ?? defaultLogLevel
if isPaused, !self.lastPaused {
self.pausedLogSnapshot = logList
self.lastProcessedLogCount = 0
} else if !isPaused, self.lastPaused {
self.pausedLogSnapshot = nil
self.lastProcessedLogCount = 0
}
self.lastPaused = isPaused
let sourceList = self.pausedLogSnapshot ?? logList
if isPaused, effectiveLevel == self.lastEffectiveLevel, searchText == self.lastSearchText,
self.lastProcessedLogCount > 0
{
return
}
let canIncrement = self.lastProcessedLogCount > 0 && let canIncrement = self.lastProcessedLogCount > 0 &&
logList.count > self.lastProcessedLogCount && sourceList.count > self.lastProcessedLogCount &&
effectiveLevel == self.lastEffectiveLevel && effectiveLevel == self.lastEffectiveLevel &&
searchText == self.lastSearchText searchText == self.lastSearchText
if canIncrement { if canIncrement {
let newLogs = logList[self.lastProcessedLogCount...] let newLogs = sourceList[self.lastProcessedLogCount...]
let newFilteredLogs = newLogs.filter { log in let newFilteredLogs = newLogs.filter { log in
log.level <= effectiveLevel && log.level <= effectiveLevel &&
(searchText.isEmpty || log.message.contains(searchText)) (searchText.isEmpty || log.message.contains(searchText))
} }
self.filteredLogs.append(contentsOf: newFilteredLogs) self.filteredLogs.append(contentsOf: newFilteredLogs)
} else { } else {
self.filteredLogs = logList.filter { log in self.filteredLogs = sourceList.filter { log in
log.level <= effectiveLevel && log.level <= effectiveLevel &&
(searchText.isEmpty || log.message.contains(searchText)) (searchText.isEmpty || log.message.contains(searchText))
} }
} }
self.updateVisibleLogs() self.updateVisibleLogs()
self.lastProcessedLogCount = logList.count self.lastProcessedLogCount = sourceList.count
self.lastEffectiveLevel = effectiveLevel self.lastEffectiveLevel = effectiveLevel
self.lastSearchText = searchText self.lastSearchText = searchText
} }
@@ -88,6 +111,8 @@ public class LogDataModel: ObservableObject {
public func clearLogs() { public func clearLogs() {
viewModel?.isPaused = false viewModel?.isPaused = false
pausedLogSnapshot = nil
lastPaused = false
lastProcessedLogCount = 0 lastProcessedLogCount = 0
lastEffectiveLevel = nil lastEffectiveLevel = nil
lastSearchText = "" lastSearchText = ""