mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Interact with polls through the TimelineController as well (creation still disabled on threaded timeline as it's not yet supported by the SDK)
This commit is contained in:
committed by
Stefan Ceriu
parent
324a203086
commit
ffe2f726e7
@@ -321,7 +321,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
presentMapNavigator(interactionMode: mode, timelineController: timelineController, animated: animated)
|
||||
|
||||
case (_, .presentPollForm(let mode), .pollForm):
|
||||
presentPollForm(mode: mode)
|
||||
guard let timelineController = (context.userInfo as? EventUserInfo)?.timelineController else {
|
||||
fatalError()
|
||||
}
|
||||
presentPollForm(mode: mode, timelineController: timelineController)
|
||||
|
||||
case (_, .presentResolveSendFailure(let failure, let sendHandle), .resolveSendFailure):
|
||||
presentResolveSendFailure(failure: failure, sendHandle: sendHandle)
|
||||
@@ -343,7 +346,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
presentRoomMembersList()
|
||||
|
||||
case (.roomDetails, .presentPollsHistory, .pollsHistory):
|
||||
presentPollsHistory()
|
||||
Task { await self.presentRoomPollsHistory(animated: animated) }
|
||||
|
||||
case (.roomDetails, .presentPinnedEventsTimeline, .pinnedEventsTimeline):
|
||||
startPinnedEventsTimelineFlow()
|
||||
@@ -392,7 +395,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
replaceRoomMemberDetailsWithUserProfile(userID: userID)
|
||||
|
||||
case (.pollsHistory, .presentPollForm(let mode), .pollsHistoryForm):
|
||||
presentPollForm(mode: mode)
|
||||
guard let timelineController = (context.userInfo as? EventUserInfo)?.timelineController else {
|
||||
fatalError()
|
||||
}
|
||||
presentPollForm(mode: mode, timelineController: timelineController)
|
||||
|
||||
case (_, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL, _)):
|
||||
guard let timelineController = (context.userInfo as? EventUserInfo)?.timelineController else {
|
||||
@@ -557,7 +563,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentPollForm(let mode):
|
||||
stateMachine.tryEvent(.presentPollForm(mode: mode))
|
||||
stateMachine.tryEvent(.presentPollForm(mode: mode),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentLocationViewer(_, let geoURI, let description):
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .viewOnly(geoURI: geoURI, description: description)),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
@@ -642,7 +649,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentPollForm(let mode):
|
||||
stateMachine.tryEvent(.presentPollForm(mode: mode))
|
||||
stateMachine.tryEvent(.presentPollForm(mode: mode),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
case .presentLocationViewer(_, let geoURI, let description):
|
||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .viewOnly(geoURI: geoURI,
|
||||
description: description)),
|
||||
@@ -1034,7 +1042,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func presentPollForm(mode: PollFormMode) {
|
||||
private func presentPollForm(mode: PollFormMode, timelineController: TimelineControllerProtocol) {
|
||||
let stackCoordinator = NavigationStackCoordinator()
|
||||
let coordinator = PollFormScreenCoordinator(parameters: .init(mode: mode))
|
||||
stackCoordinator.setRootCoordinator(coordinator)
|
||||
@@ -1055,9 +1063,16 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case let .submit(question, options, pollKind):
|
||||
switch mode {
|
||||
case .new:
|
||||
createPoll(question: question, options: options, pollKind: pollKind)
|
||||
createPoll(question: question,
|
||||
options: options,
|
||||
pollKind: pollKind,
|
||||
timelineController: timelineController)
|
||||
case .edit(let eventID, _):
|
||||
editPoll(pollStartID: eventID, question: question, options: options, pollKind: pollKind)
|
||||
editPoll(pollStartID: eventID,
|
||||
question: question,
|
||||
options: options,
|
||||
pollKind: pollKind,
|
||||
timelineController: timelineController)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1068,9 +1083,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func createPoll(question: String, options: [String], pollKind: Poll.Kind) {
|
||||
private func createPoll(question: String, options: [String], pollKind: Poll.Kind, timelineController: TimelineControllerProtocol) {
|
||||
Task {
|
||||
let result = await roomProxy.timeline.createPoll(question: question, answers: options, pollKind: pollKind)
|
||||
let result = await timelineController.createPoll(question: question, answers: options, pollKind: pollKind)
|
||||
|
||||
self.analytics.trackComposer(inThread: false,
|
||||
isEditing: false,
|
||||
@@ -1089,9 +1104,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func editPoll(pollStartID: String, question: String, options: [String], pollKind: Poll.Kind) {
|
||||
private func editPoll(pollStartID: String, question: String, options: [String], pollKind: Poll.Kind, timelineController: TimelineControllerProtocol) {
|
||||
Task {
|
||||
let result = await roomProxy.timeline.editPoll(original: pollStartID, question: question, answers: options, pollKind: pollKind)
|
||||
let result = await timelineController.editPoll(original: pollStartID, question: question, answers: options, pollKind: pollKind)
|
||||
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -1120,13 +1135,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func presentPollsHistory() {
|
||||
Task {
|
||||
await asyncPresentRoomPollsHistory()
|
||||
}
|
||||
}
|
||||
|
||||
private func asyncPresentRoomPollsHistory() async {
|
||||
private func presentRoomPollsHistory(animated: Bool) async {
|
||||
let userID = userSession.clientProxy.userID
|
||||
|
||||
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
||||
@@ -1138,7 +1147,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
timelineItemFactory: timelineItemFactory,
|
||||
mediaProvider: userSession.mediaProvider)
|
||||
|
||||
let parameters = RoomPollsHistoryScreenCoordinatorParameters(pollInteractionHandler: PollInteractionHandler(analyticsService: analytics, roomProxy: roomProxy),
|
||||
let parameters = RoomPollsHistoryScreenCoordinatorParameters(pollInteractionHandler: PollInteractionHandler(analyticsService: analytics,
|
||||
timelineController: timelineController),
|
||||
timelineController: timelineController)
|
||||
let coordinator = RoomPollsHistoryScreenCoordinator(parameters: parameters)
|
||||
coordinator.actions
|
||||
@@ -1147,7 +1157,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch action {
|
||||
case .editPoll(let pollStartID, let poll):
|
||||
stateMachine.tryEvent(.presentPollForm(mode: .edit(eventID: pollStartID, poll: poll)))
|
||||
stateMachine.tryEvent(.presentPollForm(mode: .edit(eventID: pollStartID, poll: poll)),
|
||||
userInfo: EventUserInfo(animated: animated, timelineController: timelineController))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -17752,76 +17752,6 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
||||
return editPollOriginalQuestionAnswersPollKindReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - endPoll
|
||||
|
||||
var endPollPollStartIDTextUnderlyingCallsCount = 0
|
||||
var endPollPollStartIDTextCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return endPollPollStartIDTextUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = endPollPollStartIDTextUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
endPollPollStartIDTextUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
endPollPollStartIDTextUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var endPollPollStartIDTextCalled: Bool {
|
||||
return endPollPollStartIDTextCallsCount > 0
|
||||
}
|
||||
var endPollPollStartIDTextReceivedArguments: (pollStartID: String, text: String)?
|
||||
var endPollPollStartIDTextReceivedInvocations: [(pollStartID: String, text: String)] = []
|
||||
|
||||
var endPollPollStartIDTextUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||
var endPollPollStartIDTextReturnValue: Result<Void, TimelineProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return endPollPollStartIDTextUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = endPollPollStartIDTextUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
endPollPollStartIDTextUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
endPollPollStartIDTextUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var endPollPollStartIDTextClosure: ((String, String) async -> Result<Void, TimelineProxyError>)?
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineProxyError> {
|
||||
endPollPollStartIDTextCallsCount += 1
|
||||
endPollPollStartIDTextReceivedArguments = (pollStartID: pollStartID, text: text)
|
||||
DispatchQueue.main.async {
|
||||
self.endPollPollStartIDTextReceivedInvocations.append((pollStartID: pollStartID, text: text))
|
||||
}
|
||||
if let endPollPollStartIDTextClosure = endPollPollStartIDTextClosure {
|
||||
return await endPollPollStartIDTextClosure(pollStartID, text)
|
||||
} else {
|
||||
return endPollPollStartIDTextReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - sendPollResponse
|
||||
|
||||
var sendPollResponsePollStartIDAnswersUnderlyingCallsCount = 0
|
||||
@@ -17892,6 +17822,76 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
||||
return sendPollResponsePollStartIDAnswersReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - endPoll
|
||||
|
||||
var endPollPollStartIDTextUnderlyingCallsCount = 0
|
||||
var endPollPollStartIDTextCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return endPollPollStartIDTextUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = endPollPollStartIDTextUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
endPollPollStartIDTextUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
endPollPollStartIDTextUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var endPollPollStartIDTextCalled: Bool {
|
||||
return endPollPollStartIDTextCallsCount > 0
|
||||
}
|
||||
var endPollPollStartIDTextReceivedArguments: (pollStartID: String, text: String)?
|
||||
var endPollPollStartIDTextReceivedInvocations: [(pollStartID: String, text: String)] = []
|
||||
|
||||
var endPollPollStartIDTextUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||
var endPollPollStartIDTextReturnValue: Result<Void, TimelineProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return endPollPollStartIDTextUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = endPollPollStartIDTextUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
endPollPollStartIDTextUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
endPollPollStartIDTextUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var endPollPollStartIDTextClosure: ((String, String) async -> Result<Void, TimelineProxyError>)?
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineProxyError> {
|
||||
endPollPollStartIDTextCallsCount += 1
|
||||
endPollPollStartIDTextReceivedArguments = (pollStartID: pollStartID, text: text)
|
||||
DispatchQueue.main.async {
|
||||
self.endPollPollStartIDTextReceivedInvocations.append((pollStartID: pollStartID, text: text))
|
||||
}
|
||||
if let endPollPollStartIDTextClosure = endPollPollStartIDTextClosure {
|
||||
return await endPollPollStartIDTextClosure(pollStartID, text)
|
||||
} else {
|
||||
return endPollPollStartIDTextReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - getLoadedReplyDetails
|
||||
|
||||
var getLoadedReplyDetailsEventIDUnderlyingCallsCount = 0
|
||||
|
||||
@@ -85,7 +85,9 @@ class TimelineInteractionHandler {
|
||||
self.emojiProvider = emojiProvider
|
||||
self.timelineControllerFactory = timelineControllerFactory
|
||||
self.clientProxy = clientProxy
|
||||
pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService, roomProxy: roomProxy)
|
||||
|
||||
pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService,
|
||||
timelineController: timelineController)
|
||||
}
|
||||
|
||||
// MARK: Timeline Item Action Menu
|
||||
|
||||
@@ -9,22 +9,22 @@ import Foundation
|
||||
|
||||
class PollInteractionHandler: PollInteractionHandlerProtocol {
|
||||
let analyticsService: AnalyticsService
|
||||
let roomProxy: JoinedRoomProxyProtocol
|
||||
let timelineController: TimelineControllerProtocol
|
||||
|
||||
init(analyticsService: AnalyticsService, roomProxy: JoinedRoomProxyProtocol) {
|
||||
init(analyticsService: AnalyticsService, timelineController: TimelineControllerProtocol) {
|
||||
self.analyticsService = analyticsService
|
||||
self.roomProxy = roomProxy
|
||||
self.timelineController = timelineController
|
||||
}
|
||||
|
||||
func sendPollResponse(pollStartID: String, optionID: String) async -> Result<Void, Error> {
|
||||
let sendPollResponseResult = await roomProxy.timeline.sendPollResponse(pollStartID: pollStartID, answers: [optionID])
|
||||
let sendPollResponseResult = await timelineController.sendPollResponse(pollStartID: pollStartID, answers: [optionID])
|
||||
analyticsService.trackPollVote()
|
||||
|
||||
|
||||
return sendPollResponseResult.mapError { $0 }
|
||||
}
|
||||
|
||||
func endPoll(pollStartID: String) async -> Result<Void, Error> {
|
||||
let endPollResult = await roomProxy.timeline.endPoll(pollStartID: pollStartID,
|
||||
let endPollResult = await timelineController.endPoll(pollStartID: pollStartID,
|
||||
text: "The poll with event id: \(pollStartID) has ended")
|
||||
analyticsService.trackPollEnd()
|
||||
return endPollResult.mapError { $0 }
|
||||
|
||||
@@ -244,6 +244,24 @@ class MockTimelineController: TimelineControllerProtocol {
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
// MARK: - Polls
|
||||
|
||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
|
||||
.success(())
|
||||
}
|
||||
|
||||
func editPoll(original eventID: String, question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
|
||||
.success(())
|
||||
}
|
||||
|
||||
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineControllerError> {
|
||||
.success(())
|
||||
}
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineControllerError> {
|
||||
.success(())
|
||||
}
|
||||
|
||||
// MARK: - UI Test signalling
|
||||
|
||||
|
||||
@@ -362,6 +362,24 @@ class TimelineController: TimelineControllerProtocol {
|
||||
waveform: waveform, requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
|
||||
// MARK: - Polls
|
||||
|
||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
|
||||
await activeTimeline.createPoll(question: question, answers: answers, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
|
||||
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 sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineControllerError> {
|
||||
await activeTimeline.sendPollResponse(pollStartID: pollStartID, answers: answers).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineControllerError> {
|
||||
await activeTimeline.endPoll(pollStartID: pollStartID, text: text).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
/// The cancellable used to update the timeline items.
|
||||
|
||||
+13
@@ -131,4 +131,17 @@ protocol TimelineControllerProtocol {
|
||||
audioInfo: AudioInfo,
|
||||
waveform: [UInt16],
|
||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineControllerError>
|
||||
|
||||
// MARK: - Poll
|
||||
|
||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError>
|
||||
|
||||
func editPoll(original eventID: String,
|
||||
question: String,
|
||||
answers: [String],
|
||||
pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError>
|
||||
|
||||
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineControllerError>
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineControllerError>
|
||||
}
|
||||
|
||||
@@ -131,10 +131,10 @@ protocol TimelineProxyProtocol {
|
||||
answers: [String],
|
||||
pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func getLoadedReplyDetails(eventID: String) async -> Result<InReplyToDetails, TimelineProxyError>
|
||||
|
||||
func buildMessageContentFor(_ message: String,
|
||||
|
||||
Reference in New Issue
Block a user