mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
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
|
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
|
//MARK: - elementCallWidgetDriver
|
||||||
|
|
||||||
var elementCallWidgetDriverCallsCount = 0
|
var elementCallWidgetDriverCallsCount = 0
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ struct RoomProxyMockConfiguration {
|
|||||||
var canonicalAlias: String?
|
var canonicalAlias: String?
|
||||||
var alternativeAliases: [String] = []
|
var alternativeAliases: [String] = []
|
||||||
var hasUnreadNotifications = Bool.random()
|
var hasUnreadNotifications = Bool.random()
|
||||||
var canUserTriggerRoomNotification = false
|
|
||||||
|
|
||||||
var timeline = {
|
var timeline = {
|
||||||
let mock = TimelineProxyMock()
|
let mock = TimelineProxyMock()
|
||||||
@@ -45,6 +44,9 @@ struct RoomProxyMockConfiguration {
|
|||||||
var memberForID: RoomMemberProxyMock = .mockMe
|
var memberForID: RoomMemberProxyMock = .mockMe
|
||||||
var ownUserID = "@alice:somewhere.org"
|
var ownUserID = "@alice:somewhere.org"
|
||||||
|
|
||||||
|
var canUserTriggerRoomNotification = false
|
||||||
|
var canUserJoinCall = false
|
||||||
|
|
||||||
var invitedMembersCount = 100
|
var invitedMembersCount = 100
|
||||||
var joinedMembersCount = 50
|
var joinedMembersCount = 50
|
||||||
var activeMembersCount = 25
|
var activeMembersCount = 25
|
||||||
@@ -94,5 +96,6 @@ extension RoomProxyMock {
|
|||||||
getMemberUserIDReturnValue = .success(configuration.memberForID)
|
getMemberUserIDReturnValue = .success(configuration.memberForID)
|
||||||
canUserRedactUserIDReturnValue = .success(false)
|
canUserRedactUserIDReturnValue = .success(false)
|
||||||
canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification)
|
canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification)
|
||||||
|
canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ struct RoomScreenViewState: BindableState {
|
|||||||
|
|
||||||
var ownUserID: String
|
var ownUserID: String
|
||||||
|
|
||||||
|
var canJoinCall = false
|
||||||
var hasOngoingCall = false
|
var hasOngoingCall = false
|
||||||
|
|
||||||
var bindings: RoomScreenViewStateBindings
|
var bindings: RoomScreenViewStateBindings
|
||||||
|
|||||||
@@ -115,6 +115,13 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
// Note: beware if we get to e.g. restore a reply / edit,
|
// Note: beware if we get to e.g. restore a reply / edit,
|
||||||
// maybe we are tracking a non-needed first initial state
|
// maybe we are tracking a non-needed first initial state
|
||||||
trackComposerMode(.default)
|
trackComposerMode(.default)
|
||||||
|
|
||||||
|
Task {
|
||||||
|
let userID = roomProxy.ownUserID
|
||||||
|
if case let .success(permission) = await roomProxy.canUserJoinCall(userID: userID) {
|
||||||
|
state.canJoinCall = permission
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ struct RoomScreen: View {
|
|||||||
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||||
ToolbarItem(placement: .primaryAction) {
|
ToolbarItem(placement: .primaryAction) {
|
||||||
callButton
|
callButton
|
||||||
|
.disabled(context.viewState.canJoinCall == false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,22 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
let secureBackupController: SecureBackupControllerProtocol
|
let secureBackupController: SecureBackupControllerProtocol
|
||||||
|
|
||||||
private let roomListRecencyOrderingAllowedEventTypes = ["m.room.message", "m.room.encrypted", "m.sticker"]
|
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 var loadCachedAvatarURLTask: Task<Void, Never>?
|
||||||
private let userAvatarURLSubject = CurrentValueSubject<URL?, Never>(nil)
|
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> {
|
func createDirectRoom(with userID: String, expectedRoomName: String?) async -> Result<String, ClientProxyError> {
|
||||||
let result: Result<String, ClientProxyError> = await Task.dispatch(on: clientQueue) {
|
let result: Result<String, ClientProxyError> = await Task.dispatch(on: clientQueue) {
|
||||||
do {
|
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)
|
let result = try self.client.createRoom(request: parameters)
|
||||||
return .success(result)
|
return .success(result)
|
||||||
} catch {
|
} catch {
|
||||||
@@ -229,7 +253,8 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
visibility: isRoomPrivate ? .private : .public,
|
visibility: isRoomPrivate ? .private : .public,
|
||||||
preset: isRoomPrivate ? .privateChat : .publicChat,
|
preset: isRoomPrivate ? .privateChat : .publicChat,
|
||||||
invite: userIDs,
|
invite: userIDs,
|
||||||
avatar: avatarURL?.absoluteString)
|
avatar: avatarURL?.absoluteString,
|
||||||
|
powerLevelContentOverride: Self.roomCreationPowerLevelOverrides)
|
||||||
let roomID = try self.client.createRoom(request: parameters)
|
let roomID = try self.client.createRoom(request: parameters)
|
||||||
return .success(roomID)
|
return .success(roomID)
|
||||||
} catch {
|
} 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
|
// MARK: - Element Call
|
||||||
|
|
||||||
func elementCallWidgetDriver() -> ElementCallWidgetDriverProtocol {
|
func elementCallWidgetDriver() -> ElementCallWidgetDriverProtocol {
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ protocol RoomProxyProtocol {
|
|||||||
|
|
||||||
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError>
|
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
|
|
||||||
|
func canUserJoinCall(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
|
|
||||||
// MARK: - Element Call
|
// MARK: - Element Call
|
||||||
|
|
||||||
func elementCallWidgetDriver() -> ElementCallWidgetDriverProtocol
|
func elementCallWidgetDriver() -> ElementCallWidgetDriverProtocol
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
|||||||
func testUserSuggestonsIncludingAllUsers() async throws {
|
func testUserSuggestonsIncludingAllUsers() async throws {
|
||||||
let alice: RoomMemberProxyMock = .mockAlice
|
let alice: RoomMemberProxyMock = .mockAlice
|
||||||
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
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)
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||||
|
|
||||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||||
@@ -92,7 +92,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
|||||||
let alice: RoomMemberProxyMock = .mockAlice
|
let alice: RoomMemberProxyMock = .mockAlice
|
||||||
let bob: RoomMemberProxyMock = .mockBob
|
let bob: RoomMemberProxyMock = .mockBob
|
||||||
let members: [RoomMemberProxyMock] = [alice, bob, .mockMe]
|
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)
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||||
|
|
||||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:14aa29c8a73cb71b322ba5ba067ebe8f317b477cf4db754c93902061465a1413
|
oid sha256:b04690d8cebb4b16b56075243f5a337728c51fc7a72c3be0ef6dc60d7d7aede2
|
||||||
size 308497
|
size 308386
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:14aa29c8a73cb71b322ba5ba067ebe8f317b477cf4db754c93902061465a1413
|
oid sha256:b04690d8cebb4b16b56075243f5a337728c51fc7a72c3be0ef6dc60d7d7aede2
|
||||||
size 308497
|
size 308386
|
||||||
|
|||||||
Reference in New Issue
Block a user