113 lines
3.4 KiB
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)
|
|
}
|
|
}
|