Refactor data sources and feed model
This commit is contained in:
@@ -10,7 +10,7 @@ import Foundation
|
||||
final class FeedStore {
|
||||
struct CardKey: Hashable, Codable {
|
||||
let id: String
|
||||
let type: WinnerType
|
||||
let type: FeedItemType
|
||||
}
|
||||
|
||||
struct CardState: Codable, Equatable {
|
||||
@@ -58,17 +58,17 @@ final class FeedStore {
|
||||
}
|
||||
}
|
||||
|
||||
func lastShownAt(candidateId: String) -> Int? {
|
||||
func lastShownAt(feedItemId: String) -> Int? {
|
||||
queue.sync {
|
||||
let matches = states.compactMap { (key, value) -> Int? in
|
||||
guard key.hasSuffix("|" + candidateId) else { return nil }
|
||||
guard key.hasSuffix("|" + feedItemId) else { return nil }
|
||||
return value.lastShownAt
|
||||
}
|
||||
return matches.max()
|
||||
}
|
||||
}
|
||||
|
||||
func isSuppressed(id: String, type: WinnerType, now: Int) -> Bool {
|
||||
func isSuppressed(id: String, type: FeedItemType, now: Int) -> Bool {
|
||||
queue.sync {
|
||||
let key = Self.keyString(id: id, type: type)
|
||||
guard let state = states[key] else { return false }
|
||||
@@ -78,7 +78,7 @@ final class FeedStore {
|
||||
}
|
||||
}
|
||||
|
||||
func dismiss(id: String, type: WinnerType, until: Int? = nil) {
|
||||
func dismiss(id: String, type: FeedItemType, until: Int? = nil) {
|
||||
queue.sync {
|
||||
let key = Self.keyString(id: id, type: type)
|
||||
var state = states[key] ?? CardState()
|
||||
@@ -88,7 +88,7 @@ final class FeedStore {
|
||||
}
|
||||
}
|
||||
|
||||
func snooze(id: String, type: WinnerType, until: Int) {
|
||||
func snooze(id: String, type: FeedItemType, until: Int) {
|
||||
queue.sync {
|
||||
let key = Self.keyString(id: id, type: type)
|
||||
var state = states[key] ?? CardState()
|
||||
@@ -98,7 +98,7 @@ final class FeedStore {
|
||||
}
|
||||
}
|
||||
|
||||
func clearSuppression(id: String, type: WinnerType) {
|
||||
func clearSuppression(id: String, type: FeedItemType) {
|
||||
queue.sync {
|
||||
let key = Self.keyString(id: id, type: type)
|
||||
var state = states[key] ?? CardState()
|
||||
@@ -119,11 +119,11 @@ final class FeedStore {
|
||||
}
|
||||
|
||||
private func normalizedFeed(_ feed: FeedEnvelope, now: Int, applyingSuppression: Bool = true) -> FeedEnvelope {
|
||||
let normalizedCards = feed.feed.compactMap { card -> FeedCard? in
|
||||
let normalizedCards = feed.feed.compactMap { card -> FeedItem? in
|
||||
let ttl = max(1, card.ttlSec)
|
||||
if feed.generatedAt + ttl <= now { return nil }
|
||||
if applyingSuppression, isSuppressedUnlocked(id: card.id, type: card.type, now: now) { return nil }
|
||||
return FeedCard(
|
||||
return FeedItem(
|
||||
id: card.id,
|
||||
type: card.type,
|
||||
title: card.title.truncated(maxLength: TextConstraints.titleMax),
|
||||
@@ -131,6 +131,7 @@ final class FeedStore {
|
||||
priority: min(max(card.priority, 0.0), 1.0),
|
||||
ttlSec: ttl,
|
||||
condition: card.condition,
|
||||
startsAt: card.startsAt,
|
||||
bucket: card.bucket,
|
||||
actions: card.actions
|
||||
)
|
||||
@@ -146,7 +147,7 @@ final class FeedStore {
|
||||
return normalized
|
||||
}
|
||||
|
||||
private func isSuppressedUnlocked(id: String, type: WinnerType, now: Int) -> Bool {
|
||||
private func isSuppressedUnlocked(id: String, type: FeedItemType, now: Int) -> Bool {
|
||||
let key = Self.keyString(id: id, type: type)
|
||||
guard let state = states[key] else { return false }
|
||||
if let until = state.dismissedUntil, until > now { return true }
|
||||
@@ -159,7 +160,7 @@ final class FeedStore {
|
||||
Self.save(persisted, to: fileURL)
|
||||
}
|
||||
|
||||
private static func keyString(id: String, type: WinnerType) -> String {
|
||||
private static func keyString(id: String, type: FeedItemType) -> String {
|
||||
"\(type.rawValue)|\(id)"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user