Adopt room info power levels (#4245)

* Use the newly RoomInfo published PowerLevels; update permissions at the same time as the room info and avoid unnecessary async calls.

* Introduce a RoomInfoProxyProtocol and associated mock and move away from mocked SDK RoomInfos

* Bump the SDK to v25.06.23

* Expose new non-throwing methods for checking one's own user permissions

* Fix the unit and preview tests (except the TimelineMediaPreviewDetails for which simplified snapshots were generated)

* Converge on one single implementation for computing a room's avatar.

* Fix more unit tests

* Fix the TimelineMediaPreviewDetailsView snapshot tests

This reverts commit 9b6c819e611ad2fa3de2c34a4a7aa556fc9faadd.

---------

Co-authored-by: Doug <douglase@element.io>
This commit is contained in:
Stefan Ceriu
2025-06-24 19:48:00 +03:00
committed by GitHub
parent 0f9d700c99
commit 5ac6ec28d5
31 changed files with 1274 additions and 362 deletions
@@ -19,47 +19,52 @@ struct BannedRoomProxyMockConfiguration {
extension BannedRoomProxyMock {
@MainActor
convenience init(_ configuration: KnockedRoomProxyMockConfiguration) {
convenience init(_ configuration: BannedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
info = RoomInfoProxy(roomInfo: .init(configuration))
info = RoomInfoProxyMock(configuration)
}
}
extension RoomInfo {
@MainActor init(_ configuration: BannedRoomProxyMockConfiguration) {
self.init(id: configuration.id,
encryptionState: .notEncrypted,
creator: nil,
displayName: configuration.name,
rawName: nil,
topic: nil,
avatarUrl: configuration.avatarURL?.absoluteString,
isDirect: false,
isPublic: false,
isSpace: false,
successorRoom: nil,
isFavourite: false,
canonicalAlias: nil,
alternativeAliases: [],
membership: .knocked,
inviter: nil,
heroes: [],
activeMembersCount: UInt64(configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count),
invitedMembersCount: UInt64(configuration.members.filter { $0.membership == .invite }.count),
joinedMembersCount: UInt64(configuration.members.filter { $0.membership == .join }.count),
userPowerLevels: [:],
highlightCount: 0,
notificationCount: 0,
cachedUserDefinedNotificationMode: nil,
hasRoomCall: false,
activeRoomCallParticipants: [],
isMarkedUnread: false,
numUnreadMessages: 0,
numUnreadNotifications: 0,
numUnreadMentions: 0,
pinnedEventIds: [],
joinRule: .knock,
historyVisibility: .shared)
extension RoomInfoProxyMock {
@MainActor convenience init(_ configuration: BannedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
isEncrypted = false
creator = nil
displayName = configuration.name
rawName = nil
topic = nil
avatarURL = configuration.avatarURL
isDirect = false
isPublic = false
isSpace = false
successor = nil
isFavourite = false
canonicalAlias = nil
alternativeAliases = []
membership = .knocked
inviter = nil
heroes = []
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = nil
hasRoomCall = false
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = []
joinRule = .knock
historyVisibility = .shared
powerLevels = RoomPowerLevelsProxyMock(configuration: .init())
}
}
@@ -6472,11 +6472,11 @@ class InvitedRoomProxyMock: InvitedRoomProxyProtocol, @unchecked Sendable {
}
}
class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
var infoPublisher: CurrentValuePublisher<RoomInfoProxy, Never> {
var infoPublisher: CurrentValuePublisher<RoomInfoProxyProtocol, Never> {
get { return underlyingInfoPublisher }
set(value) { underlyingInfoPublisher = value }
}
var underlyingInfoPublisher: CurrentValuePublisher<RoomInfoProxy, Never>!
var underlyingInfoPublisher: CurrentValuePublisher<RoomInfoProxyProtocol, Never>!
var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> {
get { return underlyingMembersPublisher }
set(value) { underlyingMembersPublisher = value }
@@ -13406,6 +13406,127 @@ class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol, @unchecked
}
}
}
class RoomInfoProxyMock: RoomInfoProxyProtocol, @unchecked Sendable {
var id: String {
get { return underlyingId }
set(value) { underlyingId = value }
}
var underlyingId: String!
var creator: String?
var displayName: String?
var rawName: String?
var topic: String?
var avatarURL: URL?
var isEncrypted: Bool {
get { return underlyingIsEncrypted }
set(value) { underlyingIsEncrypted = value }
}
var underlyingIsEncrypted: Bool!
var isDirect: Bool {
get { return underlyingIsDirect }
set(value) { underlyingIsDirect = value }
}
var underlyingIsDirect: Bool!
var isPublic: Bool {
get { return underlyingIsPublic }
set(value) { underlyingIsPublic = value }
}
var underlyingIsPublic: Bool!
var isPrivate: Bool {
get { return underlyingIsPrivate }
set(value) { underlyingIsPrivate = value }
}
var underlyingIsPrivate: Bool!
var isSpace: Bool {
get { return underlyingIsSpace }
set(value) { underlyingIsSpace = value }
}
var underlyingIsSpace: Bool!
var isFavourite: Bool {
get { return underlyingIsFavourite }
set(value) { underlyingIsFavourite = value }
}
var underlyingIsFavourite: Bool!
var canonicalAlias: String?
var alternativeAliases: [String] = []
var membership: Membership {
get { return underlyingMembership }
set(value) { underlyingMembership = value }
}
var underlyingMembership: Membership!
var inviter: RoomMemberProxyProtocol?
var activeMembersCount: Int {
get { return underlyingActiveMembersCount }
set(value) { underlyingActiveMembersCount = value }
}
var underlyingActiveMembersCount: Int!
var invitedMembersCount: Int {
get { return underlyingInvitedMembersCount }
set(value) { underlyingInvitedMembersCount = value }
}
var underlyingInvitedMembersCount: Int!
var joinedMembersCount: Int {
get { return underlyingJoinedMembersCount }
set(value) { underlyingJoinedMembersCount = value }
}
var underlyingJoinedMembersCount: Int!
var highlightCount: Int {
get { return underlyingHighlightCount }
set(value) { underlyingHighlightCount = value }
}
var underlyingHighlightCount: Int!
var notificationCount: Int {
get { return underlyingNotificationCount }
set(value) { underlyingNotificationCount = value }
}
var underlyingNotificationCount: Int!
var cachedUserDefinedNotificationMode: RoomNotificationMode?
var hasRoomCall: Bool {
get { return underlyingHasRoomCall }
set(value) { underlyingHasRoomCall = value }
}
var underlyingHasRoomCall: Bool!
var activeRoomCallParticipants: [String] = []
var isMarkedUnread: Bool {
get { return underlyingIsMarkedUnread }
set(value) { underlyingIsMarkedUnread = value }
}
var underlyingIsMarkedUnread: Bool!
var unreadMessagesCount: UInt {
get { return underlyingUnreadMessagesCount }
set(value) { underlyingUnreadMessagesCount = value }
}
var underlyingUnreadMessagesCount: UInt!
var unreadNotificationsCount: UInt {
get { return underlyingUnreadNotificationsCount }
set(value) { underlyingUnreadNotificationsCount = value }
}
var underlyingUnreadNotificationsCount: UInt!
var unreadMentionsCount: UInt {
get { return underlyingUnreadMentionsCount }
set(value) { underlyingUnreadMentionsCount = value }
}
var underlyingUnreadMentionsCount: UInt!
var pinnedEventIDs: Set<String> {
get { return underlyingPinnedEventIDs }
set(value) { underlyingPinnedEventIDs = value }
}
var underlyingPinnedEventIDs: Set<String>!
var joinRule: JoinRule?
var historyVisibility: RoomHistoryVisibility {
get { return underlyingHistoryVisibility }
set(value) { underlyingHistoryVisibility = value }
}
var underlyingHistoryVisibility: RoomHistoryVisibility!
var powerLevels: RoomPowerLevelsProxyProtocol {
get { return underlyingPowerLevels }
set(value) { underlyingPowerLevels = value }
}
var underlyingPowerLevels: RoomPowerLevelsProxyProtocol!
var successor: SuccessorRoom?
var heroes: [RoomHero] = []
}
class RoomMemberProxyMock: RoomMemberProxyProtocol, @unchecked Sendable {
var userID: String {
get { return underlyingUserID }
@@ -13467,6 +13588,658 @@ class RoomPowerLevelsProxyMock: RoomPowerLevelsProxyProtocol, @unchecked Sendabl
}
var underlyingValues: RoomPowerLevelsValues!
//MARK: - canOwnUser
var canOwnUserSendMessageUnderlyingCallsCount = 0
var canOwnUserSendMessageCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserSendMessageUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserSendMessageUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserSendMessageUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserSendMessageUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserSendMessageCalled: Bool {
return canOwnUserSendMessageCallsCount > 0
}
var canOwnUserSendMessageReceivedMessageType: MessageLikeEventType?
var canOwnUserSendMessageReceivedInvocations: [MessageLikeEventType] = []
var canOwnUserSendMessageUnderlyingReturnValue: Bool!
var canOwnUserSendMessageReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserSendMessageUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserSendMessageUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserSendMessageUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserSendMessageUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserSendMessageClosure: ((MessageLikeEventType) -> Bool)?
func canOwnUser(sendMessage messageType: MessageLikeEventType) -> Bool {
canOwnUserSendMessageCallsCount += 1
canOwnUserSendMessageReceivedMessageType = messageType
DispatchQueue.main.async {
self.canOwnUserSendMessageReceivedInvocations.append(messageType)
}
if let canOwnUserSendMessageClosure = canOwnUserSendMessageClosure {
return canOwnUserSendMessageClosure(messageType)
} else {
return canOwnUserSendMessageReturnValue
}
}
//MARK: - canOwnUser
var canOwnUserSendStateEventUnderlyingCallsCount = 0
var canOwnUserSendStateEventCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserSendStateEventUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserSendStateEventUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserSendStateEventUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserSendStateEventUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserSendStateEventCalled: Bool {
return canOwnUserSendStateEventCallsCount > 0
}
var canOwnUserSendStateEventReceivedEvent: StateEventType?
var canOwnUserSendStateEventReceivedInvocations: [StateEventType] = []
var canOwnUserSendStateEventUnderlyingReturnValue: Bool!
var canOwnUserSendStateEventReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserSendStateEventUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserSendStateEventUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserSendStateEventUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserSendStateEventUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserSendStateEventClosure: ((StateEventType) -> Bool)?
func canOwnUser(sendStateEvent event: StateEventType) -> Bool {
canOwnUserSendStateEventCallsCount += 1
canOwnUserSendStateEventReceivedEvent = event
DispatchQueue.main.async {
self.canOwnUserSendStateEventReceivedInvocations.append(event)
}
if let canOwnUserSendStateEventClosure = canOwnUserSendStateEventClosure {
return canOwnUserSendStateEventClosure(event)
} else {
return canOwnUserSendStateEventReturnValue
}
}
//MARK: - canOwnUserInvite
var canOwnUserInviteUnderlyingCallsCount = 0
var canOwnUserInviteCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserInviteUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserInviteUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserInviteUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserInviteUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserInviteCalled: Bool {
return canOwnUserInviteCallsCount > 0
}
var canOwnUserInviteUnderlyingReturnValue: Bool!
var canOwnUserInviteReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserInviteUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserInviteUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserInviteUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserInviteUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserInviteClosure: (() -> Bool)?
func canOwnUserInvite() -> Bool {
canOwnUserInviteCallsCount += 1
if let canOwnUserInviteClosure = canOwnUserInviteClosure {
return canOwnUserInviteClosure()
} else {
return canOwnUserInviteReturnValue
}
}
//MARK: - canOwnUserRedactOther
var canOwnUserRedactOtherUnderlyingCallsCount = 0
var canOwnUserRedactOtherCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserRedactOtherUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserRedactOtherUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserRedactOtherUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserRedactOtherUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserRedactOtherCalled: Bool {
return canOwnUserRedactOtherCallsCount > 0
}
var canOwnUserRedactOtherUnderlyingReturnValue: Bool!
var canOwnUserRedactOtherReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserRedactOtherUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserRedactOtherUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserRedactOtherUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserRedactOtherUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserRedactOtherClosure: (() -> Bool)?
func canOwnUserRedactOther() -> Bool {
canOwnUserRedactOtherCallsCount += 1
if let canOwnUserRedactOtherClosure = canOwnUserRedactOtherClosure {
return canOwnUserRedactOtherClosure()
} else {
return canOwnUserRedactOtherReturnValue
}
}
//MARK: - canOwnUserRedactOwn
var canOwnUserRedactOwnUnderlyingCallsCount = 0
var canOwnUserRedactOwnCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserRedactOwnUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserRedactOwnUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserRedactOwnUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserRedactOwnUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserRedactOwnCalled: Bool {
return canOwnUserRedactOwnCallsCount > 0
}
var canOwnUserRedactOwnUnderlyingReturnValue: Bool!
var canOwnUserRedactOwnReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserRedactOwnUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserRedactOwnUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserRedactOwnUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserRedactOwnUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserRedactOwnClosure: (() -> Bool)?
func canOwnUserRedactOwn() -> Bool {
canOwnUserRedactOwnCallsCount += 1
if let canOwnUserRedactOwnClosure = canOwnUserRedactOwnClosure {
return canOwnUserRedactOwnClosure()
} else {
return canOwnUserRedactOwnReturnValue
}
}
//MARK: - canOwnUserKick
var canOwnUserKickUnderlyingCallsCount = 0
var canOwnUserKickCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserKickUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserKickUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserKickUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserKickUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserKickCalled: Bool {
return canOwnUserKickCallsCount > 0
}
var canOwnUserKickUnderlyingReturnValue: Bool!
var canOwnUserKickReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserKickUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserKickUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserKickUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserKickUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserKickClosure: (() -> Bool)?
func canOwnUserKick() -> Bool {
canOwnUserKickCallsCount += 1
if let canOwnUserKickClosure = canOwnUserKickClosure {
return canOwnUserKickClosure()
} else {
return canOwnUserKickReturnValue
}
}
//MARK: - canOwnUserBan
var canOwnUserBanUnderlyingCallsCount = 0
var canOwnUserBanCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserBanUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserBanUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserBanUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserBanUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserBanCalled: Bool {
return canOwnUserBanCallsCount > 0
}
var canOwnUserBanUnderlyingReturnValue: Bool!
var canOwnUserBanReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserBanUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserBanUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserBanUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserBanUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserBanClosure: (() -> Bool)?
func canOwnUserBan() -> Bool {
canOwnUserBanCallsCount += 1
if let canOwnUserBanClosure = canOwnUserBanClosure {
return canOwnUserBanClosure()
} else {
return canOwnUserBanReturnValue
}
}
//MARK: - canOwnUserTriggerRoomNotification
var canOwnUserTriggerRoomNotificationUnderlyingCallsCount = 0
var canOwnUserTriggerRoomNotificationCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserTriggerRoomNotificationUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserTriggerRoomNotificationUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserTriggerRoomNotificationUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserTriggerRoomNotificationUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserTriggerRoomNotificationCalled: Bool {
return canOwnUserTriggerRoomNotificationCallsCount > 0
}
var canOwnUserTriggerRoomNotificationUnderlyingReturnValue: Bool!
var canOwnUserTriggerRoomNotificationReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserTriggerRoomNotificationUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserTriggerRoomNotificationUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserTriggerRoomNotificationUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserTriggerRoomNotificationUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserTriggerRoomNotificationClosure: (() -> Bool)?
func canOwnUserTriggerRoomNotification() -> Bool {
canOwnUserTriggerRoomNotificationCallsCount += 1
if let canOwnUserTriggerRoomNotificationClosure = canOwnUserTriggerRoomNotificationClosure {
return canOwnUserTriggerRoomNotificationClosure()
} else {
return canOwnUserTriggerRoomNotificationReturnValue
}
}
//MARK: - canOwnUserPinOrUnpin
var canOwnUserPinOrUnpinUnderlyingCallsCount = 0
var canOwnUserPinOrUnpinCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserPinOrUnpinUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserPinOrUnpinUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserPinOrUnpinUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserPinOrUnpinUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserPinOrUnpinCalled: Bool {
return canOwnUserPinOrUnpinCallsCount > 0
}
var canOwnUserPinOrUnpinUnderlyingReturnValue: Bool!
var canOwnUserPinOrUnpinReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserPinOrUnpinUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserPinOrUnpinUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserPinOrUnpinUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserPinOrUnpinUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserPinOrUnpinClosure: (() -> Bool)?
func canOwnUserPinOrUnpin() -> Bool {
canOwnUserPinOrUnpinCallsCount += 1
if let canOwnUserPinOrUnpinClosure = canOwnUserPinOrUnpinClosure {
return canOwnUserPinOrUnpinClosure()
} else {
return canOwnUserPinOrUnpinReturnValue
}
}
//MARK: - canOwnUserJoinCall
var canOwnUserJoinCallUnderlyingCallsCount = 0
var canOwnUserJoinCallCallsCount: Int {
get {
if Thread.isMainThread {
return canOwnUserJoinCallUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserJoinCallUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserJoinCallUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
canOwnUserJoinCallUnderlyingCallsCount = newValue
}
}
}
}
var canOwnUserJoinCallCalled: Bool {
return canOwnUserJoinCallCallsCount > 0
}
var canOwnUserJoinCallUnderlyingReturnValue: Bool!
var canOwnUserJoinCallReturnValue: Bool! {
get {
if Thread.isMainThread {
return canOwnUserJoinCallUnderlyingReturnValue
} else {
var returnValue: Bool? = nil
DispatchQueue.main.sync {
returnValue = canOwnUserJoinCallUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
canOwnUserJoinCallUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
canOwnUserJoinCallUnderlyingReturnValue = newValue
}
}
}
}
var canOwnUserJoinCallClosure: (() -> Bool)?
func canOwnUserJoinCall() -> Bool {
canOwnUserJoinCallCallsCount += 1
if let canOwnUserJoinCallClosure = canOwnUserJoinCallClosure {
return canOwnUserJoinCallClosure()
} else {
return canOwnUserJoinCallReturnValue
}
}
//MARK: - canUser
var canUserUserIDSendMessageUnderlyingCallsCount = 0
@@ -24,47 +24,52 @@ extension InvitedRoomProxyMock {
self.init()
id = configuration.id
inviter = configuration.inviter
info = RoomInfoProxy(roomInfo: .init(configuration))
info = RoomInfoProxyMock(configuration)
rejectInvitationReturnValue = .success(())
}
}
extension RoomInfo {
@MainActor init(_ configuration: InvitedRoomProxyMockConfiguration) {
self.init(id: configuration.id,
encryptionState: .notEncrypted,
creator: nil,
displayName: configuration.name,
rawName: nil,
topic: nil,
avatarUrl: configuration.avatarURL?.absoluteString,
isDirect: false,
isPublic: false,
isSpace: false,
successorRoom: nil,
isFavourite: false,
canonicalAlias: nil,
alternativeAliases: [],
membership: .knocked,
inviter: .init(configuration.inviter),
heroes: [],
activeMembersCount: UInt64(configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count),
invitedMembersCount: UInt64(configuration.members.filter { $0.membership == .invite }.count),
joinedMembersCount: UInt64(configuration.members.filter { $0.membership == .join }.count),
userPowerLevels: [:],
highlightCount: 0,
notificationCount: 0,
cachedUserDefinedNotificationMode: nil,
hasRoomCall: false,
activeRoomCallParticipants: [],
isMarkedUnread: false,
numUnreadMessages: 0,
numUnreadNotifications: 0,
numUnreadMentions: 0,
pinnedEventIds: [],
joinRule: .invite,
historyVisibility: .shared)
extension RoomInfoProxyMock {
@MainActor convenience init(_ configuration: InvitedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
isEncrypted = false
creator = nil
displayName = configuration.name
rawName = nil
topic = nil
avatarURL = configuration.avatarURL
isDirect = false
isPublic = false
isSpace = false
successor = nil
isFavourite = false
canonicalAlias = nil
alternativeAliases = []
membership = .knocked
inviter = .init(configuration.inviter)
heroes = []
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = nil
hasRoomCall = false
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = []
joinRule = .invite
historyVisibility = .shared
powerLevels = RoomPowerLevelsProxyMock(configuration: .init())
}
}
@@ -62,7 +62,6 @@ extension JoinedRoomProxyMock {
ownUserID = configuration.ownUserID
infoPublisher = CurrentValueSubject(.init(roomInfo: .init(configuration))).asCurrentValuePublisher()
membersPublisher = CurrentValueSubject(configuration.members).asCurrentValuePublisher()
knockRequestsStatePublisher = CurrentValueSubject(configuration.knockRequestsState).asCurrentValuePublisher()
typingMembersPublisher = CurrentValueSubject([]).asCurrentValuePublisher()
@@ -134,53 +133,52 @@ extension JoinedRoomProxyMock {
isVisibleInRoomDirectoryReturnValue = .success(configuration.isVisibleInPublicDirectory)
predecessorRoom = configuration.predecessor
let roomInfoProxyMock = RoomInfoProxyMock(configuration)
roomInfoProxyMock.powerLevels = powerLevelsProxyMock
infoPublisher = CurrentValueSubject(roomInfoProxyMock).asCurrentValuePublisher()
}
}
extension RoomInfo {
@MainActor init(_ configuration: JoinedRoomProxyMockConfiguration) {
self.init(id: configuration.id,
encryptionState: configuration.isEncrypted ? .encrypted : .notEncrypted,
creator: nil,
displayName: configuration.name,
rawName: configuration.name,
topic: configuration.topic,
avatarUrl: configuration.avatarURL?.absoluteString,
isDirect: configuration.isDirect,
isPublic: configuration.isPublic,
isSpace: configuration.isSpace,
successorRoom: configuration.successor,
isFavourite: false,
canonicalAlias: configuration.canonicalAlias,
alternativeAliases: configuration.alternativeAliases,
membership: configuration.membership,
inviter: configuration.inviter.map { RoomMember(userId: $0.userID,
displayName: $0.displayName,
avatarUrl: $0.avatarURL?.absoluteString,
membership: $0.membership,
isNameAmbiguous: false,
powerLevel: Int64($0.powerLevel),
normalizedPowerLevel: Int64($0.powerLevel),
isIgnored: $0.isIgnored,
suggestedRoleForPowerLevel: $0.role,
membershipChangeReason: $0.membershipChangeReason) },
heroes: configuration.heroes.map(RoomHero.init),
activeMembersCount: UInt64(configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count),
invitedMembersCount: UInt64(configuration.members.filter { $0.membership == .invite }.count),
joinedMembersCount: UInt64(configuration.members.filter { $0.membership == .join }.count),
userPowerLevels: [:],
highlightCount: 0,
notificationCount: 0,
cachedUserDefinedNotificationMode: .allMessages,
hasRoomCall: configuration.hasOngoingCall,
activeRoomCallParticipants: [],
isMarkedUnread: false,
numUnreadMessages: 0,
numUnreadNotifications: 0,
numUnreadMentions: 0,
pinnedEventIds: Array(configuration.pinnedEventIDs),
joinRule: configuration.joinRule,
historyVisibility: .shared)
extension RoomInfoProxyMock {
@MainActor convenience init(_ configuration: JoinedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
isEncrypted = configuration.isEncrypted
creator = nil
displayName = configuration.name
rawName = configuration.name
topic = configuration.topic
avatarURL = configuration.avatarURL
isDirect = configuration.isDirect
isPublic = configuration.isPublic
isSpace = configuration.isSpace
successor = configuration.successor
isFavourite = false
canonicalAlias = configuration.canonicalAlias
alternativeAliases = configuration.alternativeAliases
membership = configuration.membership
inviter = configuration.inviter
heroes = configuration.heroes.map(RoomHero.init)
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = .allMessages
hasRoomCall = configuration.hasOngoingCall
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = configuration.pinnedEventIDs
joinRule = configuration.joinRule
historyVisibility = .shared
powerLevels = RoomPowerLevelsProxyMock(configuration: configuration.powerLevelsConfiguration)
}
}
@@ -22,44 +22,49 @@ extension KnockedRoomProxyMock {
convenience init(_ configuration: KnockedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
info = RoomInfoProxy(roomInfo: .init(configuration))
info = RoomInfoProxyMock(configuration)
}
}
extension RoomInfo {
@MainActor init(_ configuration: KnockedRoomProxyMockConfiguration) {
self.init(id: configuration.id,
encryptionState: .notEncrypted,
creator: nil,
displayName: configuration.name,
rawName: nil,
topic: nil,
avatarUrl: configuration.avatarURL?.absoluteString,
isDirect: false,
isPublic: false,
isSpace: false,
successorRoom: nil,
isFavourite: false,
canonicalAlias: nil,
alternativeAliases: [],
membership: .knocked,
inviter: nil,
heroes: [],
activeMembersCount: UInt64(configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count),
invitedMembersCount: UInt64(configuration.members.filter { $0.membership == .invite }.count),
joinedMembersCount: UInt64(configuration.members.filter { $0.membership == .join }.count),
userPowerLevels: [:],
highlightCount: 0,
notificationCount: 0,
cachedUserDefinedNotificationMode: nil,
hasRoomCall: false,
activeRoomCallParticipants: [],
isMarkedUnread: false,
numUnreadMessages: 0,
numUnreadNotifications: 0,
numUnreadMentions: 0,
pinnedEventIds: [],
joinRule: .knock,
historyVisibility: .shared)
extension RoomInfoProxyMock {
@MainActor convenience init(_ configuration: KnockedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
isEncrypted = false
creator = nil
displayName = configuration.name
rawName = nil
topic = nil
avatarURL = configuration.avatarURL
isDirect = false
isPublic = false
isSpace = false
successor = nil
isFavourite = false
canonicalAlias = nil
alternativeAliases = []
membership = .knocked
inviter = nil
heroes = []
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = nil
hasRoomCall = false
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = []
joinRule = .knock
historyVisibility = .shared
powerLevels = RoomPowerLevelsProxyMock(configuration: .init())
}
}
@@ -26,6 +26,17 @@ extension RoomPowerLevelsProxyMock {
underlyingValues = RoomPowerLevelsValues.mock
canOwnUserSendMessageReturnValue = configuration.canUserSendMessage
canOwnUserSendStateEventReturnValue = configuration.canUserSendState
canOwnUserInviteReturnValue = configuration.canUserInvite
canOwnUserRedactOtherReturnValue = configuration.canUserRedactOther
canOwnUserRedactOwnReturnValue = configuration.canUserRedactOwn
canOwnUserKickReturnValue = configuration.canUserKick
canOwnUserBanReturnValue = configuration.canUserBan
canOwnUserTriggerRoomNotificationReturnValue = configuration.canUserTriggerRoomNotification
canOwnUserPinOrUnpinReturnValue = configuration.canUserPin
canOwnUserJoinCallReturnValue = configuration.canUserJoinCall
canUserUserIDSendMessageReturnValue = .success(configuration.canUserSendMessage)
canUserUserIDSendStateEventReturnValue = .success(configuration.canUserSendState)
canUserInviteUserIDReturnValue = .success(configuration.canUserInvite)