Stabilize beta release with warning cleanup and edge-case fixes

This commit is contained in:
Trey t
2026-02-22 13:18:14 -06:00
parent fddea81e36
commit ec2bbb4764
55 changed files with 712 additions and 315 deletions

View File

@@ -16,6 +16,7 @@ enum PollError: Error, LocalizedError {
case pollNotFound
case alreadyVoted
case notPollOwner
case notVoteOwner
case networkUnavailable
case encodingError
case unknown(Error)
@@ -30,6 +31,8 @@ enum PollError: Error, LocalizedError {
return "You have already voted on this poll."
case .notPollOwner:
return "Only the poll owner can perform this action."
case .notVoteOwner:
return "Only the vote owner can update this vote."
case .networkUnavailable:
return "Unable to connect. Please check your internet connection."
case .encodingError:
@@ -49,7 +52,7 @@ actor PollService {
private let publicDatabase: CKDatabase
private var currentUserRecordID: String?
private var pollSubscriptionID: CKSubscription.ID?
private var pollSubscriptionIDs: Set<CKSubscription.ID> = []
private init() {
self.container = CloudKitContainerConfig.makeContainer()
@@ -231,7 +234,7 @@ actor PollService {
func updateVote(_ vote: PollVote) async throws -> PollVote {
let userId = try await getCurrentUserRecordID()
guard vote.odg == userId else {
throw PollError.notPollOwner // Using this error for now - voter can only update own vote
throw PollError.notVoteOwner
}
// Fetch the existing record to get the server's changeTag
@@ -245,6 +248,13 @@ actor PollService {
throw PollError.unknown(error)
}
guard let existingVoterId = existingRecord[CKPollVote.voterIdKey] as? String else {
throw PollError.encodingError
}
guard existingVoterId == userId else {
throw PollError.notVoteOwner
}
// Update the fields on the fetched record
let now = Date()
existingRecord[CKPollVote.rankingsKey] = vote.rankings
@@ -320,11 +330,12 @@ actor PollService {
// MARK: - Subscriptions
func subscribeToVoteUpdates(forPollId pollId: UUID) async throws {
let subscriptionId = "poll-votes-\(pollId.uuidString)"
let predicate = NSPredicate(format: "%K == %@", CKPollVote.pollIdKey, pollId.uuidString)
let subscription = CKQuerySubscription(
recordType: CKRecordType.pollVote,
predicate: predicate,
subscriptionID: "poll-votes-\(pollId.uuidString)",
subscriptionID: subscriptionId,
options: [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion]
)
@@ -334,10 +345,12 @@ actor PollService {
do {
try await publicDatabase.save(subscription)
pollSubscriptionID = subscription.subscriptionID
pollSubscriptionIDs.insert(subscription.subscriptionID)
} catch let error as CKError {
// Subscription already exists is OK
if error.code != .serverRejectedRequest {
if error.code == .serverRejectedRequest {
pollSubscriptionIDs.insert(subscriptionId)
} else {
throw mapCloudKitError(error)
}
} catch {
@@ -345,14 +358,23 @@ actor PollService {
}
}
func unsubscribeFromVoteUpdates() async throws {
guard let subscriptionID = pollSubscriptionID else { return }
func unsubscribeFromVoteUpdates(forPollId pollId: UUID? = nil) async throws {
let subscriptionIds: [CKSubscription.ID]
if let pollId {
subscriptionIds = ["poll-votes-\(pollId.uuidString)"]
} else {
subscriptionIds = Array(pollSubscriptionIDs)
}
do {
try await publicDatabase.deleteSubscription(withID: subscriptionID)
pollSubscriptionID = nil
} catch {
// Ignore errors - subscription may not exist
guard !subscriptionIds.isEmpty else { return }
for subscriptionID in subscriptionIds {
do {
try await publicDatabase.deleteSubscription(withID: subscriptionID)
} catch {
// Ignore errors - subscription may not exist
}
pollSubscriptionIDs.remove(subscriptionID)
}
}