Move POI alerts to FYI #1
@@ -327,6 +327,7 @@ final class ContextOrchestrator: NSObject, ObservableObject {
|
||||
if pois.isEmpty {
|
||||
logger.info("no points of interests found")
|
||||
}
|
||||
// POIs are FYI-only; do not compete for the right-now winner.
|
||||
for poi in pois.prefix(2) {
|
||||
let subtitle = poiSubtitle(for: poi)
|
||||
let confidence = min(max(poi.confidence, 0.0), 1.0)
|
||||
@@ -344,7 +345,6 @@ final class ContextOrchestrator: NSObject, ObservableObject {
|
||||
actions: ["DISMISS"]
|
||||
)
|
||||
poiItems.append(item)
|
||||
rightNowCandidates.append(.init(item: item, confidence: confidence, isEligibleForRightNow: true))
|
||||
}
|
||||
case .failure(let error):
|
||||
fetchFailed = true
|
||||
@@ -402,10 +402,17 @@ final class ContextOrchestrator: NSObject, ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
let eligibleUnsuppressed = rightNowCandidates.filter { ranked in
|
||||
!store.isSuppressed(id: ranked.item.id, type: ranked.item.type, now: nowEpoch)
|
||||
let poiCandidateCount = rightNowCandidates.filter { $0.item.type == .poiNearby }.count
|
||||
if poiCandidateCount > 0 {
|
||||
logger.warning("dropping poi candidates from right-now ranking count=\(poiCandidateCount)")
|
||||
}
|
||||
|
||||
let eligibleUnsuppressed = rightNowCandidates
|
||||
.filter { $0.item.type != .poiNearby }
|
||||
.filter { ranked in
|
||||
!store.isSuppressed(id: ranked.item.id, type: ranked.item.type, now: nowEpoch)
|
||||
}
|
||||
|
||||
let winnerSelection = ranker.pickWinner(from: eligibleUnsuppressed, now: nowEpoch, context: userContext)
|
||||
let winnerItem = winnerSelection?.item ?? FeedEnvelope.allQuiet(now: nowEpoch).feed[0]
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ struct OrchestratorView: View {
|
||||
Button("Recompute Now") { orchestrator.recomputeNow() }
|
||||
}
|
||||
|
||||
Section("Feed") {
|
||||
Section("Winner") {
|
||||
if let feed = orchestrator.lastFeed, let winner = feed.winnerItem() {
|
||||
Text(winner.title)
|
||||
.font(.headline)
|
||||
@@ -54,36 +54,56 @@ struct OrchestratorView: View {
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Text("type \(winner.type.rawValue) • prio \(String(format: "%.2f", winner.priority)) • ttl \(winner.ttlSec)s")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
if feed.feed.count > 1 {
|
||||
Divider()
|
||||
LabeledContent("Type") { Text(winner.type.rawValue) }
|
||||
LabeledContent("Bucket") { Text(winner.bucket.rawValue) }
|
||||
LabeledContent("Priority") { Text(String(format: "%.2f", winner.priority)) }
|
||||
LabeledContent("TTL") { Text("\(winner.ttlSec)s") }
|
||||
if let poiType = winner.poiType {
|
||||
LabeledContent("POI type") { Text(poiType.rawValue) }
|
||||
}
|
||||
if let startsAt = winner.startsAt {
|
||||
LabeledContent("Starts at") { Text("\(startsAt)") }
|
||||
}
|
||||
LabeledContent("ID") {
|
||||
Text(winner.id)
|
||||
.font(.caption)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
} else {
|
||||
Text("No winner yet")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
ForEach(feed.feed, id: \.id) { item in
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack {
|
||||
Text(item.title)
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
Spacer()
|
||||
Text(item.type.rawValue)
|
||||
Section("Feed") {
|
||||
if let feed = orchestrator.lastFeed {
|
||||
if feed.feed.isEmpty {
|
||||
Text("No feed items yet")
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
ForEach(feed.feed, id: \.id) { item in
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack {
|
||||
Text(item.title)
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
Spacer()
|
||||
Text(item.type.rawValue)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
if !item.subtitle.isEmpty {
|
||||
Text(item.subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Text("bucket \(item.bucket.rawValue) • prio \(String(format: "%.2f", item.priority)) • ttl \(item.ttlSec)s")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
if !item.subtitle.isEmpty {
|
||||
Text(item.subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Text("bucket \(item.bucket.rawValue) • prio \(String(format: "%.2f", item.priority)) • ttl \(item.ttlSec)s")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
} else {
|
||||
Text("No feed yet")
|
||||
|
||||
Reference in New Issue
Block a user