Element Call permission tweaks (#2187)
* vector-im/element-meta/issues/2230 - Specify `call.member` default power levels when creating a room * vector-im/element-meta/issues/2229 - Take into account permissions when configuring the room screen call button
This commit is contained in:
@@ -2357,6 +2357,27 @@ class RoomProxyMock: RoomProxyProtocol {
|
||||
return canUserTriggerRoomNotificationUserIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - canUserJoinCall
|
||||
|
||||
var canUserJoinCallUserIDCallsCount = 0
|
||||
var canUserJoinCallUserIDCalled: Bool {
|
||||
return canUserJoinCallUserIDCallsCount > 0
|
||||
}
|
||||
var canUserJoinCallUserIDReceivedUserID: String?
|
||||
var canUserJoinCallUserIDReceivedInvocations: [String] = []
|
||||
var canUserJoinCallUserIDReturnValue: Result<Bool, RoomProxyError>!
|
||||
var canUserJoinCallUserIDClosure: ((String) async -> Result<Bool, RoomProxyError>)?
|
||||
|
||||
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||
canUserJoinCallUserIDCallsCount += 1
|
||||
canUserJoinCallUserIDReceivedUserID = userID
|
||||
canUserJoinCallUserIDReceivedInvocations.append(userID)
|
||||
if let canUserJoinCallUserIDClosure = canUserJoinCallUserIDClosure {
|
||||
return await canUserJoinCallUserIDClosure(userID)
|
||||
} else {
|
||||
return canUserJoinCallUserIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - elementCallWidgetDriver
|
||||
|
||||
var elementCallWidgetDriverCallsCount = 0
|
||||
|
||||
@@ -32,7 +32,6 @@ struct RoomProxyMockConfiguration {
|
||||
var canonicalAlias: String?
|
||||
var alternativeAliases: [String] = []
|
||||
var hasUnreadNotifications = Bool.random()
|
||||
var canUserTriggerRoomNotification = false
|
||||
|
||||
var timeline = {
|
||||
let mock = TimelineProxyMock()
|
||||
@@ -45,6 +44,9 @@ struct RoomProxyMockConfiguration {
|
||||
var memberForID: RoomMemberProxyMock = .mockMe
|
||||
var ownUserID = "@alice:somewhere.org"
|
||||
|
||||
var canUserTriggerRoomNotification = false
|
||||
var canUserJoinCall = false
|
||||
|
||||
var invitedMembersCount = 100
|
||||
var joinedMembersCount = 50
|
||||
var activeMembersCount = 25
|
||||
@@ -94,5 +96,6 @@ extension RoomProxyMock {
|
||||
getMemberUserIDReturnValue = .success(configuration.memberForID)
|
||||
canUserRedactUserIDReturnValue = .success(false)
|
||||
canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification)
|
||||
canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ struct RoomScreenViewState: BindableState {
|
||||
|
||||
var ownUserID: String
|
||||
|
||||
var canJoinCall = false
|
||||
var hasOngoingCall = false
|
||||
|
||||
var bindings: RoomScreenViewStateBindings
|
||||
|
||||
@@ -115,6 +115,13 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
// Note: beware if we get to e.g. restore a reply / edit,
|
||||
// maybe we are tracking a non-needed first initial state
|
||||
trackComposerMode(.default)
|
||||
|
||||
Task {
|
||||
let userID = roomProxy.ownUserID
|
||||
if case let .success(permission) = await roomProxy.canUserJoinCall(userID: userID) {
|
||||
state.canJoinCall = permission
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@@ -162,6 +162,7 @@ struct RoomScreen: View {
|
||||
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
callButton
|
||||
.disabled(context.viewState.canJoinCall == false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,22 @@ class ClientProxy: ClientProxyProtocol {
|
||||
let secureBackupController: SecureBackupControllerProtocol
|
||||
|
||||
private let roomListRecencyOrderingAllowedEventTypes = ["m.room.message", "m.room.encrypted", "m.sticker"]
|
||||
|
||||
private static var roomCreationPowerLevelOverrides: PowerLevels {
|
||||
.init(usersDefault: nil,
|
||||
eventsDefault: nil,
|
||||
stateDefault: nil,
|
||||
ban: nil,
|
||||
kick: nil,
|
||||
redact: nil,
|
||||
invite: nil,
|
||||
notifications: nil,
|
||||
users: [:],
|
||||
events: [
|
||||
"m.call.member": Int32(0),
|
||||
"org.matrix.msc3401.call.member": Int32(0)
|
||||
])
|
||||
}
|
||||
|
||||
private var loadCachedAvatarURLTask: Task<Void, Never>?
|
||||
private let userAvatarURLSubject = CurrentValueSubject<URL?, Never>(nil)
|
||||
@@ -208,7 +224,15 @@ class ClientProxy: ClientProxyProtocol {
|
||||
func createDirectRoom(with userID: String, expectedRoomName: String?) async -> Result<String, ClientProxyError> {
|
||||
let result: Result<String, ClientProxyError> = await Task.dispatch(on: clientQueue) {
|
||||
do {
|
||||
let parameters = CreateRoomParameters(name: nil, topic: nil, isEncrypted: true, isDirect: true, visibility: .private, preset: .trustedPrivateChat, invite: [userID], avatar: nil)
|
||||
let parameters = CreateRoomParameters(name: nil,
|
||||
topic: nil,
|
||||
isEncrypted: true,
|
||||
isDirect: true,
|
||||
visibility: .private,
|
||||
preset: .trustedPrivateChat,
|
||||
invite: [userID],
|
||||
avatar: nil,
|
||||
powerLevelContentOverride: Self.roomCreationPowerLevelOverrides)
|
||||
let result = try self.client.createRoom(request: parameters)
|
||||
return .success(result)
|
||||
} catch {
|
||||
@@ -229,7 +253,8 @@ class ClientProxy: ClientProxyProtocol {
|
||||
visibility: isRoomPrivate ? .private : .public,
|
||||
preset: isRoomPrivate ? .privateChat : .publicChat,
|
||||
invite: userIDs,
|
||||
avatar: avatarURL?.absoluteString)
|
||||
avatar: avatarURL?.absoluteString,
|
||||
powerLevelContentOverride: Self.roomCreationPowerLevelOverrides)
|
||||
let roomID = try self.client.createRoom(request: parameters)
|
||||
return .success(roomID)
|
||||
} catch {
|
||||
|
||||
@@ -396,6 +396,15 @@ class RoomProxy: RoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try await .success(room.canUserSendState(userId: userID, stateEvent: .callMember))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can trigger room notification with error: \(error)")
|
||||
return .failure(.failedCheckingPermission)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Element Call
|
||||
|
||||
func elementCallWidgetDriver() -> ElementCallWidgetDriverProtocol {
|
||||
|
||||
@@ -114,6 +114,8 @@ protocol RoomProxyProtocol {
|
||||
|
||||
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError>
|
||||
|
||||
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError>
|
||||
|
||||
// MARK: - Element Call
|
||||
|
||||
func elementCallWidgetDriver() -> ElementCallWidgetDriverProtocol
|
||||
|
||||
@@ -66,7 +66,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
||||
func testUserSuggestonsIncludingAllUsers() async throws {
|
||||
let alice: RoomMemberProxyMock = .mockAlice
|
||||
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", canUserTriggerRoomNotification: true, members: members))
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", members: members, canUserTriggerRoomNotification: true))
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||
|
||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||
@@ -92,7 +92,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
||||
let alice: RoomMemberProxyMock = .mockAlice
|
||||
let bob: RoomMemberProxyMock = .mockBob
|
||||
let members: [RoomMemberProxyMock] = [alice, bob, .mockMe]
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", canUserTriggerRoomNotification: true, members: members))
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", members: members, canUserTriggerRoomNotification: true))
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||
|
||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:14aa29c8a73cb71b322ba5ba067ebe8f317b477cf4db754c93902061465a1413
|
||||
size 308497
|
||||
oid sha256:b04690d8cebb4b16b56075243f5a337728c51fc7a72c3be0ef6dc60d7d7aede2
|
||||
size 308386
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:14aa29c8a73cb71b322ba5ba067ebe8f317b477cf4db754c93902061465a1413
|
||||
size 308497
|
||||
oid sha256:b04690d8cebb4b16b56075243f5a337728c51fc7a72c3be0ef6dc60d7d7aede2
|
||||
size 308386
|
||||
|
||||
Reference in New Issue
Block a user