mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
Add session filter to Activity view
Dropdown in the filter bar lets users scope activity to a single session or view all. Sessions are labeled with their first user message preview. Combines with the existing tool-kind filter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,20 @@ final class ActivityViewModel {
|
||||
|
||||
var toolMessages: [HermesMessage] = []
|
||||
var filterKind: ToolKind?
|
||||
var filterSessionId: String?
|
||||
var selectedEntry: ActivityEntry?
|
||||
var sessionPreviews: [String: String] = [:]
|
||||
var isLoading = true
|
||||
|
||||
var availableSessions: [(id: String, label: String)] {
|
||||
var seen = Set<String>()
|
||||
return toolMessages.compactMap { message in
|
||||
guard seen.insert(message.sessionId).inserted else { return nil }
|
||||
let label = sessionPreviews[message.sessionId] ?? message.sessionId
|
||||
return (id: message.sessionId, label: label)
|
||||
}
|
||||
}
|
||||
|
||||
var filteredActivity: [ActivityEntry] {
|
||||
let entries = toolMessages.flatMap { message in
|
||||
message.toolCalls.map { call in
|
||||
@@ -24,10 +35,11 @@ final class ActivityViewModel {
|
||||
)
|
||||
}
|
||||
}
|
||||
if let filterKind {
|
||||
return entries.filter { $0.kind == filterKind }
|
||||
return entries.filter { entry in
|
||||
let kindOk = filterKind == nil || entry.kind == filterKind
|
||||
let sessionOk = filterSessionId == nil || entry.sessionId == filterSessionId
|
||||
return kindOk && sessionOk
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func load() async {
|
||||
@@ -38,6 +50,7 @@ final class ActivityViewModel {
|
||||
return
|
||||
}
|
||||
toolMessages = await dataService.fetchRecentToolCalls(limit: 200)
|
||||
sessionPreviews = await dataService.fetchSessionPreviews(limit: 200)
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
|
||||
@@ -21,20 +21,36 @@ struct ActivityView: View {
|
||||
}
|
||||
|
||||
private var filterBar: some View {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
FilterChip(label: "All", isSelected: viewModel.filterKind == nil) {
|
||||
viewModel.filterKind = nil
|
||||
}
|
||||
ForEach(ToolKind.allCases, id: \.rawValue) { kind in
|
||||
FilterChip(label: kind.rawValue.capitalized, isSelected: viewModel.filterKind == kind) {
|
||||
viewModel.filterKind = kind
|
||||
HStack(spacing: 12) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
FilterChip(label: "All", isSelected: viewModel.filterKind == nil) {
|
||||
viewModel.filterKind = nil
|
||||
}
|
||||
ForEach(ToolKind.allCases, id: \.rawValue) { kind in
|
||||
FilterChip(label: kind.rawValue.capitalized, isSelected: viewModel.filterKind == kind) {
|
||||
viewModel.filterKind = kind
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 8)
|
||||
Divider()
|
||||
.frame(height: 16)
|
||||
Picker(selection: $viewModel.filterSessionId) {
|
||||
Text("All Sessions").tag(String?.none)
|
||||
Divider()
|
||||
ForEach(viewModel.availableSessions, id: \.id) { session in
|
||||
Text(session.label)
|
||||
.lineLimit(1)
|
||||
.tag(String?.some(session.id))
|
||||
}
|
||||
} label: {
|
||||
EmptyView()
|
||||
}
|
||||
.frame(maxWidth: 250)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
private var activityList: some View {
|
||||
|
||||
Reference in New Issue
Block a user