diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index c3186a8a1..9ebec55db 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -17,6 +17,7 @@ "a11y_pin_field" = "PIN field"; "a11y_play" = "Play"; "a11y_poll_end" = "Ended poll"; +"a11y_polls_will_remove_selection" = "Will remove previous selection"; "a11y_polls_winning_answer" = "This is the winning answer"; "a11y_react_with" = "React with %1$@"; "a11y_react_with_other_emojis" = "React with other emojis"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index eeedc9f47..ea878d774 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -62,6 +62,8 @@ internal enum L10n { internal static func a11yPollsPercentOfTotal(_ p1: Int) -> String { return L10n.tr("Localizable", "a11y_polls_percent_of_total", p1) } + /// Will remove previous selection + internal static var a11yPollsWillRemoveSelection: String { return L10n.tr("Localizable", "a11y_polls_will_remove_selection") } /// This is the winning answer internal static var a11yPollsWinningAnswer: String { return L10n.tr("Localizable", "a11y_polls_winning_answer") } /// React with %1$@ diff --git a/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift b/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift index 48767be87..df7165b3f 100644 --- a/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift @@ -92,19 +92,33 @@ struct PollView: View { private var optionsView: some View { ForEach(poll.options, id: \.id) { option in - Button { - guard !option.isSelected else { return } - actionHandler(.selectOption(optionID: option.id)) - feedbackGenerator.impactOccurred() - } label: { - PollOptionView(pollOption: option, - showVotes: showVotes, - isFinalResult: poll.hasEnded) - .foregroundColor(progressBarColor(for: option)) + if #available(iOS 18, *) { + pollOption(option: option) + .accessibilityHint(L10n.a11yPollsWillRemoveSelection, + isEnabled: isRemovePreviousSelectionHintEnabled(option: option)) + } else { + pollOption(option: option) } - .disabled(poll.hasEnded) } } + + private func isRemovePreviousSelectionHintEnabled(option: Poll.Option) -> Bool { + !poll.hasEnded && poll.hasMaxSelections && !option.isSelected + } + + private func pollOption(option: Poll.Option) -> some View { + Button { + guard !option.isSelected else { return } + actionHandler(.selectOption(optionID: option.id)) + feedbackGenerator.impactOccurred() + } label: { + PollOptionView(pollOption: option, + showVotes: showVotes, + isFinalResult: poll.hasEnded) + .foregroundColor(progressBarColor(for: option)) + } + .disabled(poll.hasEnded) + } @ViewBuilder private var summaryView: some View { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift index 36c9d897f..0197ac751 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift @@ -37,6 +37,10 @@ struct Poll: Hashable { case disclosed case undisclosed } + + var hasMaxSelections: Bool { + options.filter(\.isSelected).count == maxSelections + } struct Option: Hashable { let id: String