pommedoro/Sources/Pommedoro/Suggestions.swift

113 lines
3.4 KiB
Swift

import Foundation
class SuggestionManager {
static let shared = SuggestionManager()
// MARK: - UserDefaults keys
private enum Keys {
static let dismissed = "pommedoro.suggestions.dismissed"
static let currentIndex = "pommedoro.suggestions.currentIndex"
static let lastShown = "pommedoro.suggestions.lastShown"
}
private let defaults = UserDefaults.standard
// MARK: - Data
private let suggestions: [String] = [
"Breathe for a few",
"Get up and walk around a minute",
"Do some pushups or something",
"Bodyweight squats, let's go",
"Maybe some crunches",
"Drink some water",
"Stretch your neck and shoulders",
"Rest your eyes, look at something far away",
"Stand up and touch your toes",
"Roll your wrists and ankles",
"Take a few deep breaths",
"Go get some water",
"Do some lunges",
"Stretch your hip flexors",
"Give your eyes a break",
"Straighten your posture, your back will thank you",
"Smile — it actually helps your mood",
"Clear your desk, clear your mind",
"Take a moment to appreciate how far you've come",
"Eat something fresh and nourishing today",
"Step outside for a minute of fresh air",
"Unclench your jaw and relax your shoulders"
]
private var dismissed: Set<Int> = []
private var currentIndex: Int = 0
private var lastShown: String = ""
// MARK: - Init (restore persisted state)
private init() {
if let savedDismissed = defaults.array(forKey: Keys.dismissed) as? [Int] {
dismissed = Set(savedDismissed)
}
currentIndex = defaults.integer(forKey: Keys.currentIndex)
lastShown = defaults.string(forKey: Keys.lastShown) ?? ""
}
// MARK: - Persistence helpers
private func persist() {
defaults.set(Array(dismissed), forKey: Keys.dismissed)
defaults.set(currentIndex, forKey: Keys.currentIndex)
defaults.set(lastShown, forKey: Keys.lastShown)
}
// MARK: - Public API
func next() -> String {
let available = availableIndices()
// If nothing is available after filtering, reset dismissed pool
if available.isEmpty {
dismissed.removeAll()
return next()
}
// Pick the next available index that isn't the last-shown suggestion
var chosen: Int? = nil
var idx = currentIndex
for _ in 0..<suggestions.count {
if available.contains(idx) && suggestions[idx] != lastShown {
chosen = idx
break
}
idx = (idx + 1) % suggestions.count
}
// If every available suggestion equals lastShown (only 1 left), allow repeat
if chosen == nil {
chosen = available.first!
}
let suggestion = suggestions[chosen!]
currentIndex = (chosen! + 1) % suggestions.count
lastShown = suggestion
persist()
return suggestion
}
func dismiss(suggestion: String) {
if let idx = suggestions.firstIndex(of: suggestion) {
dismissed.insert(idx)
persist()
}
}
// MARK: - Helpers
private func availableIndices() -> Set<Int> {
let all = Set(0..<suggestions.count)
return all.subtracting(dismissed)
}
}