mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Invite the DM recipient to a new room (#5588)
* handle the details to invite users flow. * implemented the room creation in the invite screen, and its dismissal + navigaton to the newly created room * updated preview and unit tests * pr suggestions
This commit is contained in:
+1
-1
@@ -61,7 +61,7 @@ struct InviteUsersConfirmationSheetView_Previews: PreviewProvider, TestablePrevi
|
||||
|
||||
static func makeViewModel() -> InviteUsersScreenViewModel {
|
||||
let viewModel = InviteUsersScreenViewModel(userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init()))),
|
||||
roomProxy: JoinedRoomProxyMock(.init(members: [])),
|
||||
roomType: .existingRoom(roomProxy: JoinedRoomProxyMock(.init(members: []))),
|
||||
isSkippable: true,
|
||||
userDiscoveryService: UserDiscoveryServiceMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -110,7 +110,9 @@ struct InviteUsersScreen: View {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
ForEach(context.viewState.selectedUsers, id: \.userID) { user in
|
||||
InviteUsersScreenSelectedItem(user: user, mediaProvider: context.mediaProvider) {
|
||||
InviteUsersScreenSelectedItem(user: user,
|
||||
mediaProvider: context.mediaProvider,
|
||||
isLocked: context.viewState.isInviteeMandatory(user)) {
|
||||
deselect(user)
|
||||
}
|
||||
.frame(width: selectedUserCellWidth)
|
||||
@@ -133,11 +135,18 @@ struct InviteUsersScreen: View {
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button(context.viewState.actionText) {
|
||||
context.send(viewAction: .proceed)
|
||||
if context.viewState.isSkippable, context.viewState.selectedUsers.isEmpty {
|
||||
Button(L10n.actionSkip) {
|
||||
context.send(viewAction: .proceed)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.inviteUsersScreen.proceed)
|
||||
} else {
|
||||
ToolbarButton(role: .confirm(title: L10n.actionInvite)) {
|
||||
context.send(viewAction: .proceed)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.inviteUsersScreen.proceed)
|
||||
.disabled(!context.viewState.hasInvitableSelectedUsers)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.inviteUsersScreen.proceed)
|
||||
.disabled(context.viewState.isActionDisabled)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +162,7 @@ struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let searchingViewModel = makeViewModel(searchQuery: "Alice")
|
||||
static let selectedViewModel = makeViewModel(hasSelection: true)
|
||||
static let confirmSelectedViewModel = makeViewModel(shouldConfirm: true)
|
||||
static let draftViewModel = makeViewModel(roomType: .draft(mandatoryInvitees: [.mockAlice]), isSkippable: false)
|
||||
|
||||
static var previews: some View {
|
||||
ElementNavigationStack {
|
||||
@@ -179,18 +189,28 @@ struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
|
||||
InviteUsersScreen(context: confirmSelectedViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Confirm Selected")
|
||||
|
||||
ElementNavigationStack {
|
||||
InviteUsersScreen(context: draftViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Draft (locked invitee)")
|
||||
.snapshotPreferences(expect: draftViewModel.context.$viewState.map { !$0.mandatoryInvitees.isEmpty })
|
||||
}
|
||||
|
||||
static func makeViewModel(searchQuery: String? = nil, hasSelection: Bool = false, shouldConfirm: Bool = false) -> InviteUsersScreenViewModel {
|
||||
static func makeViewModel(searchQuery: String? = nil,
|
||||
hasSelection: Bool = false,
|
||||
shouldConfirm: Bool = false,
|
||||
roomType: InviteUsersScreenRoomType? = nil,
|
||||
isSkippable: Bool = true) -> InviteUsersScreenViewModel {
|
||||
let clientProxy = ClientProxyMock(.init())
|
||||
clientProxy.recentConversationCounterpartsReturnValue = [.mockAlice, .mockBob, .mockCharlie, .mockDan, .mockVerbose]
|
||||
|
||||
|
||||
let userDiscoveryService = UserDiscoveryServiceMock()
|
||||
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
|
||||
|
||||
|
||||
let viewModel = InviteUsersScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
|
||||
roomProxy: JoinedRoomProxyMock(.init(members: [])),
|
||||
isSkippable: true,
|
||||
roomType: roomType ?? .existingRoom(roomProxy: JoinedRoomProxyMock(.init(members: []))),
|
||||
isSkippable: isSkippable,
|
||||
userDiscoveryService: userDiscoveryService,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
|
||||
+17
-7
@@ -12,6 +12,7 @@ import SwiftUI
|
||||
struct InviteUsersScreenSelectedItem: View {
|
||||
let user: UserProfileProxy
|
||||
let mediaProvider: MediaProviderProtocol?
|
||||
var isLocked = false
|
||||
let dismissAction: () -> Void
|
||||
|
||||
var body: some View {
|
||||
@@ -25,18 +26,27 @@ struct InviteUsersScreenSelectedItem: View {
|
||||
.lineLimit(1)
|
||||
}
|
||||
.accessibilityElement(children: .combine)
|
||||
.accessibilityAction(named: L10n.actionRemove, dismissAction)
|
||||
.accessibilityActions {
|
||||
if !isLocked {
|
||||
Button(L10n.actionRemove, action: dismissAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@ViewBuilder
|
||||
var avatar: some View {
|
||||
LoadableAvatarImage(url: user.avatarURL,
|
||||
name: user.displayName,
|
||||
contentID: user.userID,
|
||||
avatarSize: .user(on: .inviteUsers),
|
||||
mediaProvider: mediaProvider)
|
||||
.overlayRemoveItemButton(action: dismissAction)
|
||||
let avatarImage = LoadableAvatarImage(url: user.avatarURL,
|
||||
name: user.displayName,
|
||||
contentID: user.userID,
|
||||
avatarSize: .user(on: .inviteUsers),
|
||||
mediaProvider: mediaProvider)
|
||||
if isLocked {
|
||||
avatarImage
|
||||
} else {
|
||||
avatarImage.overlayRemoveItemButton(action: dismissAction)
|
||||
}
|
||||
}
|
||||
|
||||
var closeButtonLabel: some View {
|
||||
|
||||
Reference in New Issue
Block a user