mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 04:18:31 +00:00
Use our own JoinRule type which doesn't include the reserved .private case. (#5056)
* Stop using Rust's JoinRule.private in mocks. It isn't used anywhere else (see MSC4413 for more context). * Use our own JoinRule (and AllowRule) types. * Update ElementX/Sources/Services/Room/JoinRule.swift Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com> --------- Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
This commit is contained in:
@@ -168,6 +168,7 @@
|
|||||||
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; };
|
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; };
|
||||||
1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */; };
|
1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */; };
|
||||||
1AB3D8563AB12635250A6A6E /* StaticLocationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C15E0017717EAE3A1D02D005 /* StaticLocationScreenCoordinator.swift */; };
|
1AB3D8563AB12635250A6A6E /* StaticLocationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C15E0017717EAE3A1D02D005 /* StaticLocationScreenCoordinator.swift */; };
|
||||||
|
1AE4532D92E6ED42BFE87064 /* JoinRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A566F8F2C27B99E1FB80C69B /* JoinRule.swift */; };
|
||||||
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
|
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
|
||||||
1AF4A82B4332CAD2DB3EB5DA /* TopBannerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78483F0143E185EDC6ECD741 /* TopBannerModifier.swift */; };
|
1AF4A82B4332CAD2DB3EB5DA /* TopBannerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78483F0143E185EDC6ECD741 /* TopBannerModifier.swift */; };
|
||||||
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */; };
|
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */; };
|
||||||
@@ -2448,6 +2449,7 @@
|
|||||||
A4D09290C6791D6EF04F569E /* LinkNewDeviceScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceScreenModels.swift; sourceTree = "<group>"; };
|
A4D09290C6791D6EF04F569E /* LinkNewDeviceScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceScreenModels.swift; sourceTree = "<group>"; };
|
||||||
A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModel.swift; sourceTree = "<group>"; };
|
A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineFlowCoordinator.swift; sourceTree = "<group>"; };
|
A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
A566F8F2C27B99E1FB80C69B /* JoinRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRule.swift; sourceTree = "<group>"; };
|
||||||
A6B19D10B102956066AF117B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
|
A6B19D10B102956066AF117B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
|
||||||
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
|
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
|
||||||
A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = "<group>"; };
|
A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -4027,6 +4029,7 @@
|
|||||||
C30F45308428A4D9FFDB2FB8 /* BannedRoomProxy.swift */,
|
C30F45308428A4D9FFDB2FB8 /* BannedRoomProxy.swift */,
|
||||||
0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */,
|
0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */,
|
||||||
07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */,
|
07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */,
|
||||||
|
A566F8F2C27B99E1FB80C69B /* JoinRule.swift */,
|
||||||
858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */,
|
858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */,
|
||||||
8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */,
|
8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */,
|
||||||
C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */,
|
C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */,
|
||||||
@@ -8161,6 +8164,7 @@
|
|||||||
DEDBD3E9CFCC9F20CAC79881 /* JoinRoomScreenModels.swift in Sources */,
|
DEDBD3E9CFCC9F20CAC79881 /* JoinRoomScreenModels.swift in Sources */,
|
||||||
EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */,
|
EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */,
|
||||||
7B66DA4E7E5FE4D1A0FCEAA4 /* JoinRoomScreenViewModelProtocol.swift in Sources */,
|
7B66DA4E7E5FE4D1A0FCEAA4 /* JoinRoomScreenViewModelProtocol.swift in Sources */,
|
||||||
|
1AE4532D92E6ED42BFE87064 /* JoinRule.swift in Sources */,
|
||||||
F16EED85E30B83878FBC6629 /* JoinedMembersBadgeView.swift in Sources */,
|
F16EED85E30B83878FBC6629 /* JoinedMembersBadgeView.swift in Sources */,
|
||||||
261261778DEFAEFC042B875E /* JoinedRoomProxy.swift in Sources */,
|
261261778DEFAEFC042B875E /* JoinedRoomProxy.swift in Sources */,
|
||||||
7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */,
|
7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */,
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ extension RoomPreviewProxyMock {
|
|||||||
roomType: configuration.roomType,
|
roomType: configuration.roomType,
|
||||||
isHistoryWorldReadable: nil,
|
isHistoryWorldReadable: nil,
|
||||||
membership: configuration.membership,
|
membership: configuration.membership,
|
||||||
joinRule: configuration.joinRule,
|
joinRule: configuration.joinRule.rustValue,
|
||||||
isDirect: configuration.isDirect,
|
isDirect: configuration.isDirect,
|
||||||
heroes: nil))
|
heroes: nil))
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ extension [LeaveSpaceRoom] {
|
|||||||
name: "Sound",
|
name: "Sound",
|
||||||
isSpace: false,
|
isSpace: false,
|
||||||
memberCount: 20,
|
memberCount: 20,
|
||||||
joinRule: .private),
|
joinRule: .invite),
|
||||||
isLastOwner: false,
|
isLastOwner: false,
|
||||||
areCreatorsPrivileged: false),
|
areCreatorsPrivileged: false),
|
||||||
LeaveSpaceRoom(spaceRoom: SpaceRoom(id: "3",
|
LeaveSpaceRoom(spaceRoom: SpaceRoom(id: "3",
|
||||||
@@ -70,7 +70,7 @@ extension [LeaveSpaceRoom] {
|
|||||||
name: "The Theatre",
|
name: "The Theatre",
|
||||||
isSpace: true,
|
isSpace: true,
|
||||||
memberCount: 100,
|
memberCount: 100,
|
||||||
joinRule: .private,
|
joinRule: .invite,
|
||||||
childrenCount: 20),
|
childrenCount: 20),
|
||||||
isLastOwner: false,
|
isLastOwner: false,
|
||||||
areCreatorsPrivileged: false),
|
areCreatorsPrivileged: false),
|
||||||
@@ -78,7 +78,7 @@ extension [LeaveSpaceRoom] {
|
|||||||
name: "Bookings",
|
name: "Bookings",
|
||||||
isSpace: false,
|
isSpace: false,
|
||||||
memberCount: 200,
|
memberCount: 200,
|
||||||
joinRule: .private,
|
joinRule: .invite,
|
||||||
childrenCount: 0),
|
childrenCount: 0),
|
||||||
isLastOwner: true,
|
isLastOwner: true,
|
||||||
areCreatorsPrivileged: false),
|
areCreatorsPrivileged: false),
|
||||||
@@ -160,7 +160,7 @@ private extension SpaceRoom {
|
|||||||
avatarUrl: avatarURL?.absoluteString,
|
avatarUrl: avatarURL?.absoluteString,
|
||||||
roomType: isSpace ? .space : .room,
|
roomType: isSpace ? .space : .room,
|
||||||
numJoinedMembers: memberCount,
|
numJoinedMembers: memberCount,
|
||||||
joinRule: joinRule,
|
joinRule: joinRule?.rustValue,
|
||||||
worldReadable: true,
|
worldReadable: true,
|
||||||
guestCanJoin: false,
|
guestCanJoin: false,
|
||||||
isDirect: isDirect,
|
isDirect: isDirect,
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
|||||||
|
|
||||||
static let selectedSpaceViewModel = makeViewModel(selectionMode: .preSelected(SpaceServiceRoom.mock(name: "Awesome Space",
|
static let selectedSpaceViewModel = makeViewModel(selectionMode: .preSelected(SpaceServiceRoom.mock(name: "Awesome Space",
|
||||||
isSpace: true,
|
isSpace: true,
|
||||||
joinRule: .private)))
|
joinRule: .invite)))
|
||||||
|
|
||||||
static let selectedSpaceWithListViewModel = {
|
static let selectedSpaceWithListViewModel = {
|
||||||
let viewModel = makeViewModel()
|
let viewModel = makeViewModel()
|
||||||
@@ -391,7 +391,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
|||||||
let viewModel = makeViewModel(isKnockingEnabled: true,
|
let viewModel = makeViewModel(isKnockingEnabled: true,
|
||||||
selectionMode: .preSelected(SpaceServiceRoom.mock(name: "Awesome Space",
|
selectionMode: .preSelected(SpaceServiceRoom.mock(name: "Awesome Space",
|
||||||
isSpace: true,
|
isSpace: true,
|
||||||
joinRule: .private)))
|
joinRule: .invite)))
|
||||||
viewModel.context.selectedAccessType = .askToJoinWithSpaceMembers
|
viewModel.context.selectedAccessType = .askToJoinWithSpaceMembers
|
||||||
return viewModel
|
return viewModel
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
|
|||||||
state.mode = .banned(sender: nil, reason: nil)
|
state.mode = .banned(sender: nil, reason: nil)
|
||||||
default:
|
default:
|
||||||
switch spaceServiceRoom.joinRule {
|
switch spaceServiceRoom.joinRule {
|
||||||
case .private, .invite:
|
case .invite:
|
||||||
state.mode = .inviteRequired
|
state.mode = .inviteRequired
|
||||||
case .knock, .knockRestricted:
|
case .knock, .knockRestricted:
|
||||||
state.mode = appSettings.knockingEnabled ? .knockable : .joinable
|
state.mode = appSettings.knockingEnabled ? .knockable : .joinable
|
||||||
@@ -258,7 +258,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
|
|||||||
reason: membershipDetails?.ownRoomMember.membershipChangeReason)
|
reason: membershipDetails?.ownRoomMember.membershipChangeReason)
|
||||||
default:
|
default:
|
||||||
switch roomPreview.info.joinRule {
|
switch roomPreview.info.joinRule {
|
||||||
case .private, .invite:
|
case .invite:
|
||||||
state.mode = .inviteRequired
|
state.mode = .inviteRequired
|
||||||
case .knock, .knockRestricted:
|
case .knock, .knockRestricted:
|
||||||
state.mode = appSettings.knockingEnabled ? .knockable : .joinable
|
state.mode = appSettings.knockingEnabled ? .knockable : .joinable
|
||||||
|
|||||||
+2
-2
@@ -350,9 +350,9 @@ private extension SecurityAndPrivacyRoomAccessType {
|
|||||||
case .anyone:
|
case .anyone:
|
||||||
.public
|
.public
|
||||||
case .spaceMembers(let spaceIDs):
|
case .spaceMembers(let spaceIDs):
|
||||||
.restricted(rules: spaceIDs.map { .roomMembership(roomId: $0) })
|
.restricted(rules: spaceIDs.map { .roomMembership(roomID: $0) })
|
||||||
case .askToJoinWithSpaceMembers(let spaceIDs):
|
case .askToJoinWithSpaceMembers(let spaceIDs):
|
||||||
.knockRestricted(rules: spaceIDs.map { .roomMembership(roomId: $0) })
|
.knockRestricted(rules: spaceIDs.map { .roomMembership(roomID: $0) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -269,7 +269,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||||
canonicalAlias: "#room:matrix.org",
|
canonicalAlias: "#room:matrix.org",
|
||||||
members: .allMembersAsCreator,
|
members: .allMembersAsCreator,
|
||||||
joinRule: .restricted(rules: [.roomMembership(roomId: space.id)]),
|
joinRule: .restricted(rules: [.roomMembership(roomID: space.id)]),
|
||||||
isVisibleInPublicDirectory: true)),
|
isVisibleInPublicDirectory: true)),
|
||||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
||||||
spaceServiceConfiguration: .init(joinedParentSpaces: [space]))),
|
spaceServiceConfiguration: .init(joinedParentSpaces: [space]))),
|
||||||
@@ -286,7 +286,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||||
canonicalAlias: "#room:matrix.org",
|
canonicalAlias: "#room:matrix.org",
|
||||||
members: .allMembersAsCreator,
|
members: .allMembersAsCreator,
|
||||||
joinRule: .restricted(rules: spaces.map { .roomMembership(roomId: $0.id) }),
|
joinRule: .restricted(rules: spaces.map { .roomMembership(roomID: $0.id) }),
|
||||||
isVisibleInPublicDirectory: true)),
|
isVisibleInPublicDirectory: true)),
|
||||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
||||||
spaceServiceConfiguration: .init(joinedParentSpaces: spaces))),
|
spaceServiceConfiguration: .init(joinedParentSpaces: spaces))),
|
||||||
@@ -319,7 +319,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||||
canonicalAlias: "#room:matrix.org",
|
canonicalAlias: "#room:matrix.org",
|
||||||
members: .allMembersAsCreator,
|
members: .allMembersAsCreator,
|
||||||
joinRule: .knockRestricted(rules: [.roomMembership(roomId: space.id)]),
|
joinRule: .knockRestricted(rules: [.roomMembership(roomID: space.id)]),
|
||||||
isVisibleInPublicDirectory: true)),
|
isVisibleInPublicDirectory: true)),
|
||||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
||||||
spaceServiceConfiguration: .init(joinedParentSpaces: [space]))),
|
spaceServiceConfiguration: .init(joinedParentSpaces: [space]))),
|
||||||
@@ -337,7 +337,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||||
canonicalAlias: "#room:matrix.org",
|
canonicalAlias: "#room:matrix.org",
|
||||||
members: .allMembersAsCreator,
|
members: .allMembersAsCreator,
|
||||||
joinRule: .knockRestricted(rules: spaces.map { .roomMembership(roomId: $0.id) }),
|
joinRule: .knockRestricted(rules: spaces.map { .roomMembership(roomID: $0.id) }),
|
||||||
isVisibleInPublicDirectory: true)),
|
isVisibleInPublicDirectory: true)),
|
||||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
|
||||||
spaceServiceConfiguration: .init(joinedParentSpaces: spaces))),
|
spaceServiceConfiguration: .init(joinedParentSpaces: spaces))),
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview {
|
|||||||
"Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.",
|
"Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.",
|
||||||
"Diam amet sit fermentum vulputate faucibus."].joined(separator: " "),
|
"Diam amet sit fermentum vulputate faucibus."].joined(separator: " "),
|
||||||
canonicalAlias: "#subspace:matrix.org",
|
canonicalAlias: "#subspace:matrix.org",
|
||||||
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))
|
joinRule: .knockRestricted(rules: [.roomMembership(roomID: "")]))
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ struct LeaveSpaceView_Previews: PreviewProvider, TestablePreview {
|
|||||||
joinedMembersCount: 76,
|
joinedMembersCount: 76,
|
||||||
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
|
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
|
||||||
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
|
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
|
||||||
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))
|
joinRule: .knockRestricted(rules: [.roomMembership(roomID: "")]))
|
||||||
|
|
||||||
static func makeViewModel(mode: LeaveSpaceHandleProxy.Mode) -> LeaveSpaceViewModel {
|
static func makeViewModel(mode: LeaveSpaceHandleProxy.Mode) -> LeaveSpaceViewModel {
|
||||||
let rooms: [LeaveSpaceRoom] = switch mode {
|
let rooms: [LeaveSpaceRoom] = switch mode {
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ struct SpaceScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
|
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
|
||||||
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
|
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
|
||||||
canonicalAlias: "#engineering-team:element.io",
|
canonicalAlias: "#engineering-team:element.io",
|
||||||
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))
|
joinRule: .knockRestricted(rules: [.roomMembership(roomID: "")]))
|
||||||
let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom,
|
let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom,
|
||||||
initialSpaceRooms: isNewSpace ? [] : .mockSpaceList))
|
initialSpaceRooms: isNewSpace ? [] : .mockSpaceList))
|
||||||
|
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
invite: userIDs,
|
invite: userIDs,
|
||||||
avatar: avatarURL?.absoluteString,
|
avatar: avatarURL?.absoluteString,
|
||||||
powerLevelContentOverride: powerLevelContentOverride,
|
powerLevelContentOverride: powerLevelContentOverride,
|
||||||
joinRuleOverride: accessType.joinRuleOverride,
|
joinRuleOverride: accessType.joinRuleOverride?.rustValue,
|
||||||
historyVisibilityOverride: accessType.historyVisibilityOverride,
|
historyVisibilityOverride: accessType.historyVisibilityOverride,
|
||||||
// This is an FFI naming mistake, what is required is the `aliasLocalPart` not the whole alias
|
// This is an FFI naming mistake, what is required is the `aliasLocalPart` not the whole alias
|
||||||
canonicalAlias: aliasLocalPart,
|
canonicalAlias: aliasLocalPart,
|
||||||
@@ -1432,9 +1432,9 @@ private extension CreateRoomAccessType {
|
|||||||
case .askToJoin:
|
case .askToJoin:
|
||||||
.knock
|
.knock
|
||||||
case .spaceMembers(let spaceID):
|
case .spaceMembers(let spaceID):
|
||||||
.restricted(rules: [.roomMembership(roomId: spaceID)])
|
.restricted(rules: [.roomMembership(roomID: spaceID)])
|
||||||
case .askToJoinWithSpaceMembers(let spaceID):
|
case .askToJoinWithSpaceMembers(let spaceID):
|
||||||
.knockRestricted(rules: [.roomMembership(roomId: spaceID)])
|
.knockRestricted(rules: [.roomMembership(roomID: spaceID)])
|
||||||
case .private, .public:
|
case .private, .public:
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2026 Element Creations 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
|
||||||
|
|
||||||
|
/// The rule used for users wishing to join a room.
|
||||||
|
public enum JoinRule: Equatable, Hashable {
|
||||||
|
/// Anyone can join the room without any prior action.
|
||||||
|
case `public`
|
||||||
|
/// A user who wishes to join the room must first receive an invite.
|
||||||
|
case invite
|
||||||
|
/// Users can join the room if they are invited, or they can request an invite to the room.
|
||||||
|
///
|
||||||
|
/// They can be allowed (invited) or denied (kicked/banned) access.
|
||||||
|
case knock
|
||||||
|
/// Users can join the room if they are invited, or if they meet any of the conditions described
|
||||||
|
/// in a set of ``AllowRule``s.
|
||||||
|
case restricted(rules: [AllowRule])
|
||||||
|
/// Users can join the room if they are invited, or if they meet any of the conditions described
|
||||||
|
/// in a set of ``AllowRule``s, or they can request an invite to the room.
|
||||||
|
case knockRestricted(rules: [AllowRule])
|
||||||
|
/// A custom join rule, up for interpretation by the consumer.
|
||||||
|
case custom(rawValue: String)
|
||||||
|
|
||||||
|
init(rustValue: MatrixRustSDK.JoinRule) {
|
||||||
|
self = switch rustValue {
|
||||||
|
case .public: .public
|
||||||
|
case .invite: .invite
|
||||||
|
case .knock: .knock
|
||||||
|
case .private: .invite // Assume .private is .invite – private shouldn't be used (see MSC4413).
|
||||||
|
case .restricted(let rules): .restricted(rules: rules.map(AllowRule.init))
|
||||||
|
case .knockRestricted(let rules): .knockRestricted(rules: rules.map(AllowRule.init))
|
||||||
|
case .custom(let rawValue): .custom(rawValue: rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rustValue: MatrixRustSDK.JoinRule {
|
||||||
|
switch self {
|
||||||
|
case .public: .public
|
||||||
|
case .invite: .invite
|
||||||
|
case .knock: .knock
|
||||||
|
case .restricted(rules: let rules): .restricted(rules: rules.map(\.rustValue))
|
||||||
|
case .knockRestricted(rules: let rules): .knockRestricted(rules: rules.map(\.rustValue))
|
||||||
|
case .custom(let rawValue): .custom(repr: rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An allow rule which defines a condition that allows joining a room.
|
||||||
|
public enum AllowRule: Equatable, Hashable {
|
||||||
|
/// Only a member of the `room_id` Room can join the one this rule is used in.
|
||||||
|
case roomMembership(roomID: String)
|
||||||
|
/// A custom allow rule implementation, containing its JSON representation as a `String`.
|
||||||
|
case custom(json: String)
|
||||||
|
|
||||||
|
init(rustValue: MatrixRustSDK.AllowRule) {
|
||||||
|
self = switch rustValue {
|
||||||
|
case .roomMembership(let roomID): .roomMembership(roomID: roomID)
|
||||||
|
case .custom(let json): .custom(json: json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rustValue: MatrixRustSDK.AllowRule {
|
||||||
|
switch self {
|
||||||
|
case .roomMembership(let roomID): .roomMembership(roomId: roomID)
|
||||||
|
case .custom(let json): .custom(json: json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -479,7 +479,7 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
|
|
||||||
func updateJoinRule(_ rule: JoinRule) async -> Result<Void, RoomProxyError> {
|
func updateJoinRule(_ rule: JoinRule) async -> Result<Void, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
try await room.updateJoinRules(newRule: rule)
|
try await room.updateJoinRules(newRule: rule.rustValue)
|
||||||
return .success(())
|
return .success(())
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed updating join rule with error: \(error)")
|
MXLog.error("Failed updating join rule with error: \(error)")
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ struct RoomInfoProxy: RoomInfoProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var joinRule: JoinRule? {
|
var joinRule: JoinRule? {
|
||||||
roomInfo.joinRule
|
roomInfo.joinRule.map(JoinRule.init)
|
||||||
}
|
}
|
||||||
|
|
||||||
var historyVisibility: RoomHistoryVisibility {
|
var historyVisibility: RoomHistoryVisibility {
|
||||||
@@ -193,7 +193,7 @@ struct RoomPreviewInfoProxy: BaseRoomInfoProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var joinRule: JoinRule? {
|
var joinRule: JoinRule? {
|
||||||
roomPreviewInfo.joinRule
|
roomPreviewInfo.joinRule.map(JoinRule.init)
|
||||||
}
|
}
|
||||||
|
|
||||||
var membership: Membership? {
|
var membership: Membership? {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ extension RoomInfoProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return switch joinRule {
|
return switch joinRule {
|
||||||
case .invite, .knock, .restricted, .knockRestricted, .private:
|
case .invite, .knock, .restricted, .knockRestricted:
|
||||||
true
|
true
|
||||||
case .public:
|
case .public:
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ struct SpaceServiceRoom {
|
|||||||
.public
|
.public
|
||||||
case .restricted, .knockRestricted:
|
case .restricted, .knockRestricted:
|
||||||
.restricted
|
.restricted
|
||||||
case .invite, .knock, .private, .custom:
|
case .invite, .knock, .custom:
|
||||||
.private
|
.private
|
||||||
case .none:
|
case .none:
|
||||||
.none
|
.none
|
||||||
@@ -77,7 +77,7 @@ extension SpaceServiceRoom {
|
|||||||
topic = spaceRoom.topic
|
topic = spaceRoom.topic
|
||||||
canonicalAlias = spaceRoom.canonicalAlias
|
canonicalAlias = spaceRoom.canonicalAlias
|
||||||
|
|
||||||
joinRule = spaceRoom.joinRule
|
joinRule = spaceRoom.joinRule.map(JoinRule.init)
|
||||||
worldReadable = spaceRoom.worldReadable
|
worldReadable = spaceRoom.worldReadable
|
||||||
guestCanJoin = spaceRoom.guestCanJoin
|
guestCanJoin = spaceRoom.guestCanJoin
|
||||||
state = spaceRoom.state
|
state = spaceRoom.state
|
||||||
@@ -130,10 +130,10 @@ extension SpaceServiceRoom {
|
|||||||
case .restricted:
|
case .restricted:
|
||||||
joinRule = .restricted(rules: [])
|
joinRule = .restricted(rules: [])
|
||||||
case .inviteRequired:
|
case .inviteRequired:
|
||||||
joinRule = .private
|
joinRule = .invite
|
||||||
case .invited:
|
case .invited:
|
||||||
state = .invited
|
state = .invited
|
||||||
joinRule = .private
|
joinRule = .invite
|
||||||
case .knockable:
|
case .knockable:
|
||||||
joinRule = .knock
|
joinRule = .knock
|
||||||
case .knocked:
|
case .knocked:
|
||||||
@@ -218,7 +218,7 @@ extension [SpaceServiceRoom] {
|
|||||||
childrenCount: 1,
|
childrenCount: 1,
|
||||||
joinedMembersCount: 500,
|
joinedMembersCount: 500,
|
||||||
canonicalAlias: "#the-foundation:matrix.org",
|
canonicalAlias: "#the-foundation:matrix.org",
|
||||||
joinRule: .private,
|
joinRule: .invite,
|
||||||
state: .joined),
|
state: .joined),
|
||||||
SpaceServiceRoom.mock(id: "space2",
|
SpaceServiceRoom.mock(id: "space2",
|
||||||
name: "The Second Foundation",
|
name: "The Second Foundation",
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCreateRoomInAnAlreadySelectedSpace() async throws {
|
func testCreateRoomInAnAlreadySelectedSpace() async throws {
|
||||||
let space = SpaceServiceRoom.mock(isSpace: true, joinRule: .private)
|
let space = SpaceServiceRoom.mock(isSpace: true, joinRule: .invite)
|
||||||
setup(spacesSelectionMode: .preSelected(space))
|
setup(spacesSelectionMode: .preSelected(space))
|
||||||
|
|
||||||
context.send(viewAction: .updateRoomName("A"))
|
context.send(viewAction: .updateRoomName("A"))
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
let expectation = expectation(description: "Join rule has updated")
|
let expectation = expectation(description: "Join rule has updated")
|
||||||
roomProxy.updateJoinRuleClosure = { value in
|
roomProxy.updateJoinRuleClosure = { value in
|
||||||
XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomId: space.id)]))
|
XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomID: space.id)]))
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
let expectation = expectation(description: "Join rule has updated")
|
let expectation = expectation(description: "Join rule has updated")
|
||||||
roomProxy.updateJoinRuleClosure = { value in
|
roomProxy.updateJoinRuleClosure = { value in
|
||||||
XCTAssertEqual(value, .knockRestricted(rules: [.roomMembership(roomId: space.id)]))
|
XCTAssertEqual(value, .knockRestricted(rules: [.roomMembership(roomID: space.id)]))
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
func testSingleUnknownSpaceMembersAccessCanBeReselected() async throws {
|
func testSingleUnknownSpaceMembersAccessCanBeReselected() async throws {
|
||||||
let singleRoom = [SpaceServiceRoom].mockSingleRoom
|
let singleRoom = [SpaceServiceRoom].mockSingleRoom
|
||||||
let space = singleRoom[0]
|
let space = singleRoom[0]
|
||||||
setupViewModel(joinedParentSpaces: [], joinRule: .restricted(rules: [.roomMembership(roomId: space.id)]))
|
setupViewModel(joinedParentSpaces: [], joinRule: .restricted(rules: [.roomMembership(roomID: space.id)]))
|
||||||
|
|
||||||
let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 0 }
|
let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 0 }
|
||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
@@ -156,7 +156,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
let expectation = expectation(description: "Join rule has updated")
|
let expectation = expectation(description: "Join rule has updated")
|
||||||
roomProxy.updateJoinRuleClosure = { value in
|
roomProxy.updateJoinRuleClosure = { value in
|
||||||
XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomId: spaces[0].id)]))
|
XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomID: spaces[0].id)]))
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
@@ -200,7 +200,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
let expectation = expectation(description: "Join rule has updated")
|
let expectation = expectation(description: "Join rule has updated")
|
||||||
roomProxy.updateJoinRuleClosure = { value in
|
roomProxy.updateJoinRuleClosure = { value in
|
||||||
XCTAssertEqual(value, .knockRestricted(rules: [.roomMembership(roomId: spaces[0].id)]))
|
XCTAssertEqual(value, .knockRestricted(rules: [.roomMembership(roomID: spaces[0].id)]))
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
func testMultipleSpacesMembersSelection() async throws {
|
func testMultipleSpacesMembersSelection() async throws {
|
||||||
let spaces = [SpaceServiceRoom].mockJoinedSpaces2
|
let spaces = [SpaceServiceRoom].mockJoinedSpaces2
|
||||||
setupViewModel(joinedParentSpaces: spaces,
|
setupViewModel(joinedParentSpaces: spaces,
|
||||||
joinRule: .restricted(rules: [.roomMembership(roomId: "unknownSpaceID")]))
|
joinRule: .restricted(rules: [.roomMembership(roomID: "unknownSpaceID")]))
|
||||||
|
|
||||||
let deferred = deferFulfillment(context.$viewState) { $0.selectableSpacesCount == 4 }
|
let deferred = deferFulfillment(context.$viewState) { $0.selectableSpacesCount == 4 }
|
||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
@@ -246,7 +246,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
let expectation = expectation(description: "Join rule has updated")
|
let expectation = expectation(description: "Join rule has updated")
|
||||||
roomProxy.updateJoinRuleClosure = { value in
|
roomProxy.updateJoinRuleClosure = { value in
|
||||||
XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomId: spaces[0].id), .roomMembership(roomId: "unknownSpaceID")]))
|
XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomID: spaces[0].id), .roomMembership(roomID: "unknownSpaceID")]))
|
||||||
expectation.fulfill()
|
expectation.fulfill()
|
||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
@@ -261,8 +261,8 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
let allSpaces = joinedParentSpaces + singleRoom
|
let allSpaces = joinedParentSpaces + singleRoom
|
||||||
setupViewModel(joinedParentSpaces: joinedParentSpaces,
|
setupViewModel(joinedParentSpaces: joinedParentSpaces,
|
||||||
topLevelSpaces: allSpaces,
|
topLevelSpaces: allSpaces,
|
||||||
joinRule: .restricted(rules: [.roomMembership(roomId: space.id),
|
joinRule: .restricted(rules: [.roomMembership(roomID: space.id),
|
||||||
.roomMembership(roomId: "unknownSpaceID")]))
|
.roomMembership(roomID: "unknownSpaceID")]))
|
||||||
|
|
||||||
let deferred = deferFulfillment(context.$viewState) { $0.selectableSpacesCount == 5 }
|
let deferred = deferFulfillment(context.$viewState) { $0.selectableSpacesCount == 5 }
|
||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
@@ -425,7 +425,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
private func setupViewModel(joinedParentSpaces: [SpaceServiceRoom],
|
private func setupViewModel(joinedParentSpaces: [SpaceServiceRoom],
|
||||||
topLevelSpaces: [SpaceServiceRoom] = [],
|
topLevelSpaces: [SpaceServiceRoom] = [],
|
||||||
joinRule: JoinRule) {
|
joinRule: ElementX.JoinRule) {
|
||||||
let appSettings = AppSettings()
|
let appSettings = AppSettings()
|
||||||
appSettings.spaceSettingsEnabled = true
|
appSettings.spaceSettingsEnabled = true
|
||||||
appSettings.knockingEnabled = true
|
appSettings.knockingEnabled = true
|
||||||
|
|||||||
Reference in New Issue
Block a user