Add max selections support for polls (#5726)

This commit is contained in:
svetoslav-sportinno
2026-06-22 14:39:12 +03:00
committed by GitHub
parent 173a927bf8
commit 30e4e6339d
49 changed files with 506 additions and 251 deletions
@@ -17,8 +17,8 @@ class PollInteractionHandler: PollInteractionHandlerProtocol {
self.timelineController = timelineController
}
func sendPollResponse(pollStartID: String, optionID: String) async -> Result<Void, Error> {
let sendPollResponseResult = await timelineController.sendPollResponse(pollStartID: pollStartID, answers: [optionID])
func sendPollResponse(pollStartID: String, answerIDs: [String]) async -> Result<Void, Error> {
let sendPollResponseResult = await timelineController.sendPollResponse(pollStartID: pollStartID, answers: answerIDs)
analyticsService.trackPollVote()
return sendPollResponseResult.mapError { $0 }
@@ -9,7 +9,7 @@
import Foundation
protocol PollInteractionHandlerProtocol {
func sendPollResponse(pollStartID: String, optionID: String) async -> Result<Void, Error>
func sendPollResponse(pollStartID: String, answerIDs: [String]) async -> Result<Void, Error>
func endPoll(pollStartID: String) async -> Result<Void, Error>
}
@@ -404,8 +404,8 @@ class TimelineController: TimelineControllerProtocol {
// MARK: - Polls
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
switch await activeTimeline.createPoll(question: question, answers: answers, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError) {
func createPoll(question: String, answers: [String], maxSelections: Int, pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
switch await activeTimeline.createPoll(question: question, answers: answers, maxSelections: maxSelections, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError) {
case .success:
callbacks.send(.messageSentOrEdited)
return .success(())
@@ -414,8 +414,8 @@ class TimelineController: TimelineControllerProtocol {
}
}
func editPoll(original eventID: String, question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
await activeTimeline.editPoll(original: eventID, question: question, answers: answers, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError)
func editPoll(original eventID: String, question: String, answers: [String], maxSelections: Int, pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
await activeTimeline.editPoll(original: eventID, question: question, answers: answers, maxSelections: maxSelections, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError)
}
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineControllerError> {
@@ -137,11 +137,12 @@ protocol TimelineControllerProtocol: Sendable {
// MARK: - Poll
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError>
func createPoll(question: String, answers: [String], maxSelections: Int, pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError>
func editPoll(original eventID: String,
question: String,
answers: [String],
maxSelections: Int,
pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError>
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineControllerError>
@@ -43,6 +43,23 @@ nonisolated struct Poll: Hashable {
options.filter(\.isSelected).count == maxSelections
}
func answerIDsAfterSelecting(optionID: String) -> [String]? {
guard options.contains(where: { $0.id == optionID }) else { return nil }
let selectedOptionIDs = options.filter(\.isSelected).map(\.id)
if selectedOptionIDs.contains(optionID) {
guard maxSelections > 1, selectedOptionIDs.count > 1 else { return nil }
return selectedOptionIDs.filter { $0 != optionID }
}
guard maxSelections > 1 else {
return [optionID]
}
guard selectedOptionIDs.count < maxSelections else { return nil }
return selectedOptionIDs + [optionID]
}
struct Option: Hashable {
let id: String
let text: String
@@ -494,12 +494,15 @@ final class TimelineProxy: TimelineProxyProtocol {
// MARK: - Polls
func createPoll(question: String, answers: [String],
func createPoll(question: String, answers: [String], maxSelections: Int,
pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError> {
MXLog.info("Creating poll")
do {
try await timeline.createPoll(question: question, answers: answers, maxSelections: 1, pollKind: .init(pollKind: pollKind))
try await timeline.createPoll(question: question,
answers: answers,
maxSelections: UInt8(max(1, min(maxSelections, answers.count))),
pollKind: .init(pollKind: pollKind))
MXLog.info("Finished creating poll")
@@ -513,6 +516,7 @@ final class TimelineProxy: TimelineProxyProtocol {
func editPoll(original eventID: String,
question: String,
answers: [String],
maxSelections: Int,
pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError> {
MXLog.info("Editing poll with eventID: \(eventID)")
@@ -522,7 +526,7 @@ final class TimelineProxy: TimelineProxyProtocol {
try await timeline.edit(eventOrTransactionId: originalEvent.eventOrTransactionId,
newContent: .pollStart(pollData: .init(question: question,
answers: answers,
maxSelections: 1,
maxSelections: UInt8(max(1, min(maxSelections, answers.count))),
pollKind: .init(pollKind: pollKind))))
MXLog.info("Finished editing poll with eventID: \(eventID)")
@@ -124,11 +124,12 @@ protocol TimelineProxyProtocol: Sendable {
func toggleReaction(_ reaction: String, to eventID: TimelineItemIdentifier.EventOrTransactionID) async -> Result<Void, TimelineProxyError>
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError>
func createPoll(question: String, answers: [String], maxSelections: Int, pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError>
func editPoll(original eventID: String,
question: String,
answers: [String],
maxSelections: Int,
pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError>
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineProxyError>