crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

FriendInviteRecencyStore.swift (1283B)


      1 import Foundation
      2 
      3 /// Device-local most-recently-used ordering for friends selected for a direct
      4 /// puzzle invite. This is a presentation preference, so it deliberately stays
      5 /// out of the synced `FriendEntity` model.
      6 @MainActor
      7 final class FriendInviteRecencyStore {
      8     private let defaults: UserDefaults
      9     private let defaultsKey = "recentlyInvitedFriendAuthorIDs"
     10     private let maximumCount = 200
     11 
     12     init(defaults: UserDefaults = .standard) {
     13         self.defaults = defaults
     14     }
     15 
     16     /// A friend selected most recently has rank zero.
     17     var ranksByAuthorID: [String: Int] {
     18         var ranks: [String: Int] = [:]
     19         for authorID in orderedAuthorIDs where ranks[authorID] == nil {
     20             ranks[authorID] = ranks.count
     21         }
     22         return ranks
     23     }
     24 
     25     /// Moves a successfully queued direct invite to the front of the ordering.
     26     func recordInvite(to authorID: String) {
     27         guard !authorID.isEmpty else { return }
     28         var authorIDs = orderedAuthorIDs
     29         authorIDs.removeAll { $0 == authorID }
     30         authorIDs.insert(authorID, at: 0)
     31         defaults.set(Array(authorIDs.prefix(maximumCount)), forKey: defaultsKey)
     32     }
     33 
     34     private var orderedAuthorIDs: [String] {
     35         defaults.stringArray(forKey: defaultsKey) ?? []
     36     }
     37 }