Last active
October 25, 2025 01:42
-
-
Save Aayush9029/40afffc39c358c346f248b37704764b6 to your computer and use it in GitHub Desktop.
Local Interval Client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Dependencies | |
| import Foundation | |
| public struct IntervalKey { | |
| let key: String | |
| let config: IntervalConfig | |
| public init(_ key: String, config: IntervalConfig) { | |
| self.key = "interval." + key | |
| self.config = config | |
| } | |
| } | |
| public struct IntervalConfig: Equatable { | |
| let component: Calendar.Component | |
| let value: Int | |
| public static let hourly = Self(component: .hour, value: 1) | |
| public static let daily = Self(component: .day, value: 1) | |
| public static let weekly = Self(component: .weekOfYear, value: 1) | |
| public static let monthly = Self(component: .month, value: 1) | |
| public static let yearly = Self(component: .year, value: 1) | |
| public static func custom(_ component: Calendar.Component, _ value: Int) -> Self { | |
| Self(component: component, value: value) | |
| } | |
| } | |
| public extension IntervalKey { | |
| static func key(_ name: String, _ config: IntervalConfig) -> IntervalKey { | |
| IntervalKey(name, config: config) | |
| } | |
| } | |
| public struct IntervalClient { | |
| public var shouldRun: @Sendable (IntervalKey) -> Bool | |
| public var markRun: @Sendable (IntervalKey) async -> Void | |
| public var reset: @Sendable (IntervalKey) async -> Void | |
| } | |
| extension IntervalClient: DependencyKey { | |
| public static let liveValue = Self( | |
| shouldRun: { key in | |
| let defaults = UserDefaults.standard | |
| // Never run before | |
| guard let lastRunTimestamp = defaults.object(forKey: key.key) as? TimeInterval else { | |
| return true | |
| } | |
| let lastRunDate = Date(timeIntervalSince1970: lastRunTimestamp) | |
| guard let nextRunDate = Calendar.current.date( | |
| byAdding: key.config.component, | |
| value: key.config.value, | |
| to: lastRunDate | |
| ) else { | |
| return true // Fallback if date calculation fails | |
| } | |
| // Handles wrap-around via proper date math | |
| return Date() >= nextRunDate | |
| }, | |
| markRun: { key in | |
| let timestamp = Date().timeIntervalSince1970 | |
| UserDefaults.standard.set(timestamp, forKey: key.key) | |
| }, | |
| reset: { key in | |
| UserDefaults.standard.removeObject(forKey: key.key) | |
| } | |
| ) | |
| } | |
| public extension DependencyValues { | |
| var intervalClient: IntervalClient { | |
| get { self[IntervalClient.self] } | |
| set { self[IntervalClient.self] = newValue } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
IntervalClient
What Does It Do?
IntervalClient prevents actions from happening too frequently.
Think of it like a cooldown timer in a game - once you use an ability, you can't use it again until the cooldown is over.
Real-World Problem
Your app wants to ask users for a review, but you don't want to annoy them:
How To Use It
Step 1: Define Your Intervals
Step 2: Use It In Your App
Timeline Example
Let's say today is January 1st, 2025 at 9:00 AM:
Available Cooldown Periods
When To Reset
That's It!
IntervalClient is just a smart timer that: