Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the JoinRoom screen to take advantage of newer APIs and support more joinRule/membership combinations (i.e. invite required, restricted, banned) #3685

Merged
merged 4 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,15 @@
"screen_invites_decline_direct_chat_title" = "Decline chat";
"screen_invites_empty_list" = "No Invites";
"screen_invites_invited_you" = "%1$@ (%2$@) invited you";
"screen_join_room_ban_by_message" = "You were banned from this room by %1$@.";
"screen_join_room_ban_message" = "You were banned from this room";
"screen_join_room_ban_reason" = "Reason: %1$@.";
"screen_join_room_fail_message" = "Joining the room failed.";
"screen_join_room_fail_reason" = "This room is either invite-only or there might be restrictions to access at space level.";
"screen_join_room_forget_action" = "Forget this room";
"screen_join_room_invite_required_message" = "You need an invite in order to join this room";
"screen_join_room_join_action" = "Join room";
"screen_join_room_join_restricted_message" = "You may need to be invited or be a member of a space in order to join.";
"screen_join_room_knock_action" = "Send request to join";
"screen_join_room_space_not_supported_description" = "%1$@ does not support spaces yet. You can access spaces on web.";
"screen_join_room_space_not_supported_title" = "Spaces are not supported yet";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,15 @@
"screen_invites_decline_direct_chat_title" = "Decline chat";
"screen_invites_empty_list" = "No Invites";
"screen_invites_invited_you" = "%1$@ (%2$@) invited you";
"screen_join_room_ban_by_message" = "You were banned from this room by %1$@.";
"screen_join_room_ban_message" = "You were banned from this room";
"screen_join_room_ban_reason" = "Reason: %1$@.";
"screen_join_room_fail_message" = "Joining the room failed.";
"screen_join_room_fail_reason" = "This room is either invite-only or there might be restrictions to access at space level.";
"screen_join_room_forget_action" = "Forget this room";
"screen_join_room_invite_required_message" = "You need an invite in order to join this room";
"screen_join_room_join_action" = "Join room";
"screen_join_room_join_restricted_message" = "You may need to be invited or be a member of a space in order to join.";
"screen_join_room_knock_action" = "Send request to join";
"screen_join_room_space_not_supported_description" = "%1$@ does not support spaces yet. You can access spaces on web.";
"screen_join_room_space_not_supported_title" = "Spaces are not supported yet";
Expand Down
20 changes: 20 additions & 0 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,16 @@ internal enum L10n {
internal static func screenInvitesInvitedYou(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "screen_invites_invited_you", String(describing: p1), String(describing: p2))
}
/// You were banned from this room by %1$@.
internal static func screenJoinRoomBanByMessage(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_join_room_ban_by_message", String(describing: p1))
}
/// You were banned from this room
internal static var screenJoinRoomBanMessage: String { return L10n.tr("Localizable", "screen_join_room_ban_message") }
/// Reason: %1$@.
internal static func screenJoinRoomBanReason(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_join_room_ban_reason", String(describing: p1))
}
/// Cancel request
internal static var screenJoinRoomCancelKnockAction: String { return L10n.tr("Localizable", "screen_join_room_cancel_knock_action") }
/// Yes, cancel
Expand All @@ -1294,8 +1304,18 @@ internal enum L10n {
internal static var screenJoinRoomCancelKnockAlertDescription: String { return L10n.tr("Localizable", "screen_join_room_cancel_knock_alert_description") }
/// Cancel request to join
internal static var screenJoinRoomCancelKnockAlertTitle: String { return L10n.tr("Localizable", "screen_join_room_cancel_knock_alert_title") }
/// Joining the room failed.
internal static var screenJoinRoomFailMessage: String { return L10n.tr("Localizable", "screen_join_room_fail_message") }
/// This room is either invite-only or there might be restrictions to access at space level.
internal static var screenJoinRoomFailReason: String { return L10n.tr("Localizable", "screen_join_room_fail_reason") }
/// Forget this room
internal static var screenJoinRoomForgetAction: String { return L10n.tr("Localizable", "screen_join_room_forget_action") }
/// You need an invite in order to join this room
internal static var screenJoinRoomInviteRequiredMessage: String { return L10n.tr("Localizable", "screen_join_room_invite_required_message") }
/// Join room
internal static var screenJoinRoomJoinAction: String { return L10n.tr("Localizable", "screen_join_room_join_action") }
/// You may need to be invited or be a member of a space in order to join.
internal static var screenJoinRoomJoinRestrictedMessage: String { return L10n.tr("Localizable", "screen_join_room_join_restricted_message") }
/// Send request to join
internal static var screenJoinRoomKnockAction: String { return L10n.tr("Localizable", "screen_join_room_knock_action") }
/// Message (optional)
Expand Down
44 changes: 39 additions & 5 deletions ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3187,13 +3187,13 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable {
var roomPreviewForIdentifierViaReceivedArguments: (identifier: String, via: [String])?
var roomPreviewForIdentifierViaReceivedInvocations: [(identifier: String, via: [String])] = []

var roomPreviewForIdentifierViaUnderlyingReturnValue: Result<RoomPreviewDetails, ClientProxyError>!
var roomPreviewForIdentifierViaReturnValue: Result<RoomPreviewDetails, ClientProxyError>! {
var roomPreviewForIdentifierViaUnderlyingReturnValue: Result<RoomPreviewProxyProtocol, ClientProxyError>!
var roomPreviewForIdentifierViaReturnValue: Result<RoomPreviewProxyProtocol, ClientProxyError>! {
get {
if Thread.isMainThread {
return roomPreviewForIdentifierViaUnderlyingReturnValue
} else {
var returnValue: Result<RoomPreviewDetails, ClientProxyError>? = nil
var returnValue: Result<RoomPreviewProxyProtocol, ClientProxyError>? = nil
DispatchQueue.main.sync {
returnValue = roomPreviewForIdentifierViaUnderlyingReturnValue
}
Expand All @@ -3211,9 +3211,9 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable {
}
}
}
var roomPreviewForIdentifierViaClosure: ((String, [String]) async -> Result<RoomPreviewDetails, ClientProxyError>)?
var roomPreviewForIdentifierViaClosure: ((String, [String]) async -> Result<RoomPreviewProxyProtocol, ClientProxyError>)?

func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result<RoomPreviewDetails, ClientProxyError> {
func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result<RoomPreviewProxyProtocol, ClientProxyError> {
roomPreviewForIdentifierViaCallsCount += 1
roomPreviewForIdentifierViaReceivedArguments = (identifier: identifier, via: via)
DispatchQueue.main.async {
Expand Down Expand Up @@ -13346,6 +13346,15 @@ class RoomMemberProxyMock: RoomMemberProxyProtocol, @unchecked Sendable {
}
var underlyingRole: RoomMemberRole!

}
class RoomMembershipDetailsProxyMock: RoomMembershipDetailsProxyProtocol, @unchecked Sendable {
var ownRoomMember: RoomMemberProxyProtocol {
get { return underlyingOwnRoomMember }
set(value) { underlyingOwnRoomMember = value }
}
var underlyingOwnRoomMember: RoomMemberProxyProtocol!
var senderRoomMember: RoomMemberProxyProtocol?

}
class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol, @unchecked Sendable {
var mode: RoomNotificationModeProxy {
Expand All @@ -13359,6 +13368,31 @@ class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol,
}
var underlyingIsDefault: Bool!

}
class RoomPreviewProxyMock: RoomPreviewProxyProtocol, @unchecked Sendable {
var info: RoomPreviewInfoProxy {
get { return underlyingInfo }
set(value) { underlyingInfo = value }
}
var underlyingInfo: RoomPreviewInfoProxy!
var ownMembershipDetailsCallsCount = 0
var ownMembershipDetailsCalled: Bool {
return ownMembershipDetailsCallsCount > 0
}

var ownMembershipDetails: RoomMembershipDetailsProxyProtocol? {
get async {
ownMembershipDetailsCallsCount += 1
if let ownMembershipDetailsClosure = ownMembershipDetailsClosure {
return await ownMembershipDetailsClosure()
} else {
return underlyingOwnMembershipDetails
}
}
}
var underlyingOwnMembershipDetails: RoomMembershipDetailsProxyProtocol?
var ownMembershipDetailsClosure: (() async -> RoomMembershipDetailsProxyProtocol?)?

}
class RoomProxyMock: RoomProxyProtocol, @unchecked Sendable {
var id: String {
Expand Down
90 changes: 90 additions & 0 deletions ElementX/Sources/Mocks/RoomPreviewProxyMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//

import Foundation
import MatrixRustSDK

extension RoomPreviewProxyMock {
stefanceriu marked this conversation as resolved.
Show resolved Hide resolved
struct Configuration {
var roomID = "1"
var canonicalAlias = "#3🌞problem:matrix.org"
var name = "The Three-Body Problem - 三体"
var topic = "“Science and technology were the only keys to opening the door to the future, and people approached science with the faith and sincerity of elementary school students.”"
var avatarURL = URL.mockMXCAvatar.absoluteString
var numJoinedMembers = UInt64(100)
var numActiveMembers = UInt64(100)
var roomType = RoomType.room
var membership: Membership?
var joinRule: JoinRule
}

static var joinable: RoomPreviewProxyMock {
.init(.init(membership: nil, joinRule: .public))
}

static var restricted: RoomPreviewProxyMock {
.init(.init(membership: nil, joinRule: .restricted(rules: [])))
}

static var inviteRequired: RoomPreviewProxyMock {
.init(.init(membership: nil, joinRule: .invite))
}

static func invited(roomID: String? = nil) -> RoomPreviewProxyMock {
if let roomID {
return .init(.init(roomID: roomID, membership: .invited, joinRule: .invite))
}

return .init(.init(membership: .invited, joinRule: .invite))
}

static var knockable: RoomPreviewProxyMock {
.init(.init(membership: nil, joinRule: .knock))
}

static var knockableRestricted: RoomPreviewProxyMock {
.init(.init(membership: nil, joinRule: .knockRestricted(rules: [])))
}

static var knocked: RoomPreviewProxyMock {
.init(.init(membership: .knocked, joinRule: .knock))
}

static var banned: RoomPreviewProxyMock {
.init(.init(membership: .banned, joinRule: .public))
}

convenience init(_ configuration: RoomPreviewProxyMock.Configuration) {
self.init()
underlyingInfo = .init(roomPreviewInfo: .init(roomId: configuration.roomID,
canonicalAlias: configuration.canonicalAlias,
name: configuration.name,
topic: configuration.topic,
avatarUrl: configuration.avatarURL,
numJoinedMembers: configuration.numJoinedMembers,
numActiveMembers: configuration.numActiveMembers,
roomType: configuration.roomType,
isHistoryWorldReadable: nil,
membership: configuration.membership,
joinRule: configuration.joinRule,
isDirect: nil,
heroes: nil))

let roomMembershipDetails = RoomMembershipDetailsProxyMock()

let mockMember = RoomMemberProxyMock()
mockMember.userID = "@bob:matrix.org"
mockMember.displayName = "Billy Bob"
mockMember.avatarURL = .mockMXCUserAvatar
mockMember.membershipChangeReason = "Ain't nobody need no reason"

roomMembershipDetails.senderRoomMember = mockMember
roomMembershipDetails.ownRoomMember = mockMember

underlyingOwnMembershipDetails = roomMembershipDetails
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ enum JoinRoomScreenViewModelAction {
case dismiss
}

enum JoinRoomScreenInteractionMode {
enum JoinRoomScreenMode: Equatable {
case loading
case unknown
case joinable
case restricted
case inviteRequired
case invited
case join
case knock
case knockable
case knocked
case banned(sender: String?, reason: String?)
}

struct JoinRoomScreenRoomDetails {
Expand All @@ -31,12 +34,11 @@ struct JoinRoomScreenRoomDetails {
}

struct JoinRoomScreenViewState: BindableState {
// Maybe use room summary details or similar here??
let roomID: String

var roomDetails: JoinRoomScreenRoomDetails?

var mode: JoinRoomScreenInteractionMode = .loading
var mode: JoinRoomScreenMode = .loading

var bindings = JoinRoomScreenViewStateBindings()

Expand All @@ -46,10 +48,14 @@ struct JoinRoomScreenViewState: BindableState {

var subtitle: String? {
switch mode {
case .loading: nil
case .unknown: L10n.screenJoinRoomSubtitleNoPreview
case .invited, .join, .knock: roomDetails?.canonicalAlias
case .knocked: nil
case .loading:
nil
case .unknown:
L10n.screenJoinRoomSubtitleNoPreview
case .knocked:
nil
default:
roomDetails?.canonicalAlias
}
}

Expand Down
Loading
Loading