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:
Stefan Ceriu
2023-12-06 13:14:23 +02:00
committed by GitHub
parent 2a2a9b6eae
commit 9db54f779a
11 changed files with 78 additions and 9 deletions

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -129,6 +129,7 @@ struct RoomScreenViewState: BindableState {
var ownUserID: String
var canJoinCall = false
var hasOngoingCall = false
var bindings: RoomScreenViewStateBindings

View File

@@ -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

View File

@@ -162,6 +162,7 @@ struct RoomScreen: View {
if !ProcessInfo.processInfo.isiOSAppOnMac {
ToolbarItem(placement: .primaryAction) {
callButton
.disabled(context.viewState.canJoinCall == false)
}
}
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:14aa29c8a73cb71b322ba5ba067ebe8f317b477cf4db754c93902061465a1413
size 308497
oid sha256:b04690d8cebb4b16b56075243f5a337728c51fc7a72c3be0ef6dc60d7d7aede2
size 308386

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:14aa29c8a73cb71b322ba5ba067ebe8f317b477cf4db754c93902061465a1413
size 308497
oid sha256:b04690d8cebb4b16b56075243f5a337728c51fc7a72c3be0ef6dc60d7d7aede2
size 308386