Skip to content

Commit

Permalink
knock request banner accept flow
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 committed Nov 29, 2024
1 parent 74074a5 commit ac1cbaf
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 21 deletions.
12 changes: 10 additions & 2 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ enum RoomScreenViewAction {
case displayRoomDetails
case displayCall
case footerViewAction(RoomScreenFooterViewAction)
case acceptKnock(userID: String)
case acceptKnock(eventID: String)
case dismissKnockRequests
case viewKnockRequests
}
Expand All @@ -49,9 +49,17 @@ struct RoomScreenViewState: BindableState {
var canDeclineKnocks = false
var canBan = false
var unseenKnockRequests: [KnockRequestInfo] = []
var handledEventIDs: Set<String> = []

var displayedKnockRequests: [KnockRequestInfo] {
unseenKnockRequests.filter { !handledEventIDs.contains($0.eventID) }
}

var shouldSeeKnockRequests: Bool {
isKnockingEnabled && isKnockableRoom && !unseenKnockRequests.isEmpty && (canAcceptKnocks || canDeclineKnocks || canBan)
isKnockingEnabled &&
isKnockableRoom &&
!displayedKnockRequests.isEmpty &&
(canAcceptKnocks || canDeclineKnocks || canBan)
}

var footerDetails: RoomScreenFooterViewDetails?
Expand Down
32 changes: 25 additions & 7 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
case .resolvePinViolation(let userID):
Task { await resolveIdentityPinningViolation(userID) }
}
case .acceptKnock(userID: let userID):
// TODO: API to accept a knock required
break
case .acceptKnock(let eventID):
Task { await acceptKnock(eventID: eventID) }
case .dismissKnockRequests:
// TODO: API to mark knocks as seen required
break
Expand Down Expand Up @@ -183,12 +182,14 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
.store(in: &cancellables)

roomProxy.requestsToJoinPublisher
// We only care about unseen requests
.map { $0.filter { !$0.isSeen } }
// If the requests have the same event ids we can discard the output
.removeDuplicates(by: { Set($0.map(\.eventID)) == Set($1.map(\.eventID)) })
.receive(on: DispatchQueue.main)
.sink { [weak self] requests in
guard let self else { return }
state.unseenKnockRequests = requests
.filter { !$0.isSeen }
.map(KnockRequestInfo.init)
state.unseenKnockRequests = requests.map(KnockRequestInfo.init)
}
.store(in: &cancellables)
}
Expand Down Expand Up @@ -288,9 +289,25 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
}
}

private func acceptKnock(eventID: String) async {
guard let knockRequest = roomProxy.requestsToJoinPublisher.value.first(where: { $0.eventID == eventID }) else {
return
}

state.handledEventIDs.insert(eventID)
switch await knockRequest.accept() {
case .success:
break
case .failure:
userIndicatorController.submitIndicator(.init(id: Self.errorIndicatorIdentifier, type: .toast, title: L10n.errorUnknown))
state.handledEventIDs.remove(eventID)
}
}

// MARK: Loading indicators

private static let loadingIndicatorIdentifier = "\(RoomScreenViewModel.self)-Loading"
private static let errorIndicatorIdentifier = "\(RoomScreenViewModel.self)-Loading"

private func showLoadingIndicator() {
userIndicatorController.submitIndicator(.init(id: Self.loadingIndicatorIdentifier, type: .toast, title: L10n.commonLoading))
Expand Down Expand Up @@ -320,6 +337,7 @@ private extension KnockRequestInfo {
self.init(displayName: proxy.displayName,
avatarURL: proxy.avatarURL,
userID: proxy.userID,
reason: proxy.reason)
reason: proxy.reason,
eventID: proxy.eventID)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct KnockRequestInfo {
let avatarURL: URL?
let userID: String
let reason: String?
let eventID: String
}

struct KnockRequestsBannerView: View {
Expand Down Expand Up @@ -103,7 +104,7 @@ private struct SingleKnockRequestBannerContent: View {
.buttonStyle(.compound(.secondary, size: .medium))
if let onAccept {
Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle, action: {
onAccept(request.userID)
onAccept(request.eventID)
})
.buttonStyle(.compound(.primary, size: .medium))
}
Expand Down Expand Up @@ -173,18 +174,18 @@ private struct KnockRequestsBannerDismissButton: View {
}

struct KnockRequestsBannerView_Previews: PreviewProvider, TestablePreview {
static let singleRequest: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil)]
static let singleRequest: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil, eventID: "1")]

static let singleRequestWithReason: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Hey, I’d like to join this room because of xyz topic and I’d like to participate in the room.")]
static let singleRequestWithReason: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Hey, I’d like to join this room because of xyz topic and I’d like to participate in the room.", eventID: "1")]

static let singleRequestNoDisplayName: [KnockRequestInfo] = [.init(displayName: nil, avatarURL: nil, userID: "@alice:matrix.org", reason: nil)]
static let singleRequestNoDisplayName: [KnockRequestInfo] = [.init(displayName: nil, avatarURL: nil, userID: "@alice:matrix.org", reason: nil, eventID: "1")]

static let multipleRequests: [KnockRequestInfo] = [
.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil),
.init(displayName: "Bob", avatarURL: nil, userID: "@bob:matrix.org", reason: nil),
.init(displayName: "Charlie", avatarURL: nil, userID: "@charlie:matrix.org", reason: nil),
.init(displayName: "Dan", avatarURL: nil, userID: "@dan:matrix.org", reason: nil),
.init(displayName: "Test", avatarURL: nil, userID: "@dan:matrix.org", reason: nil)
.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil, eventID: "1"),
.init(displayName: "Bob", avatarURL: nil, userID: "@bob:matrix.org", reason: nil, eventID: "2"),
.init(displayName: "Charlie", avatarURL: nil, userID: "@charlie:matrix.org", reason: nil, eventID: "3"),
.init(displayName: "Dan", avatarURL: nil, userID: "@dan:matrix.org", reason: nil, eventID: "4"),
.init(displayName: "Test", avatarURL: nil, userID: "@dan:matrix.org", reason: nil, eventID: "5")
]

static var previews: some View {
Expand Down
6 changes: 3 additions & 3 deletions ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ struct RoomScreen: View {
private var knockRequestsBanner: some View {
Group {
if roomContext.viewState.shouldSeeKnockRequests {
KnockRequestsBannerView(requests: roomContext.viewState.unseenKnockRequests,
KnockRequestsBannerView(requests: roomContext.viewState.displayedKnockRequests,
onDismiss: dismissKnockRequestsBanner,
onAccept: roomContext.viewState.canAcceptKnocks ? acceptKnockRequest : nil,
onViewAll: onViewAllKnockRequests,
Expand All @@ -152,8 +152,8 @@ struct RoomScreen: View {
roomContext.send(viewAction: .dismissKnockRequests)
}

private func acceptKnockRequest(userID: String) {
roomContext.send(viewAction: .acceptKnock(userID: userID))
private func acceptKnockRequest(eventID: String) {
roomContext.send(viewAction: .acceptKnock(eventID: eventID))
}

private func onViewAllKnockRequests() {
Expand Down

0 comments on commit ac1cbaf

Please sign in to comment.