mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Periphery cleanup (#5893)
This commit is contained in:
@@ -9,7 +9,7 @@ import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
/// The rule used for users wishing to join a room.
|
||||
public nonisolated enum JoinRule: Equatable, Hashable, Sendable {
|
||||
nonisolated enum JoinRule: Equatable, Hashable, Sendable {
|
||||
/// Anyone can join the room without any prior action.
|
||||
case `public`
|
||||
/// A user who wishes to join the room must first receive an invite.
|
||||
@@ -52,7 +52,7 @@ public nonisolated enum JoinRule: Equatable, Hashable, Sendable {
|
||||
}
|
||||
|
||||
/// An allow rule which defines a condition that allows joining a room.
|
||||
public nonisolated enum AllowRule: Equatable, Hashable, Sendable {
|
||||
nonisolated enum AllowRule: Equatable, Hashable, Sendable {
|
||||
/// 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`.
|
||||
|
||||
@@ -18,7 +18,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
private let analyticsService: AnalyticsServiceProtocol
|
||||
private let eventStringBuilder: RoomEventStringBuilder
|
||||
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var roomInfoObservationToken: TaskHandle?
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var typingNotificationObservationToken: TaskHandle?
|
||||
@@ -43,12 +42,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
/// The predecessor is set on room creation and never changes, so we lazily store it.
|
||||
lazy var predecessorRoom = room.predecessorRoom()
|
||||
|
||||
/// The successor may change over time, so we access it dynamically.
|
||||
/// It's suggested to observe it through the `infoPublisher`
|
||||
var successorRoom: SuccessorRoom? {
|
||||
room.successorRoom()
|
||||
}
|
||||
|
||||
let timeline: TimelineProxyProtocol
|
||||
|
||||
private let infoSubject: CurrentValueSubject<RoomInfoProxyProtocol, Never>
|
||||
@@ -301,16 +294,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func redact(_ eventID: String) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await room.redact(eventId: eventID, reason: nil)
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed redacting eventID: \(eventID) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func reportContent(_ eventID: String, reason: String?) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await room.reportContent(eventId: eventID, reason: reason)
|
||||
@@ -442,16 +425,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await room.edit(eventId: eventID, newContent: newContent)
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed editing event id \(eventID), in room \(id) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func sendTypingNotification(isTyping: Bool) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await room.typingNotice(isTyping: isTyping)
|
||||
@@ -581,15 +554,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
|
||||
// MARK: - Power Levels
|
||||
|
||||
func powerLevels() async -> Result<RoomPowerLevelsProxyProtocol?, RoomProxyError> {
|
||||
do {
|
||||
return try await .success(RoomPowerLevelsProxy(room.getPowerLevels()))
|
||||
} catch {
|
||||
MXLog.error("Failed building the current power level settings: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
return try await .success(room.applyPowerLevelChanges(changes: changes))
|
||||
@@ -609,15 +573,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func suggestedRole(for userID: String) async -> Result<RoomMemberRole, RoomProxyError> {
|
||||
do {
|
||||
return try await .success(room.suggestedRoleForUser(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed getting a user's role: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
let updates = updates.map { UserPowerLevelUpdate(userId: $0.userID, powerLevel: $0.powerLevel) }
|
||||
|
||||
@@ -16,6 +16,8 @@ nonisolated struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
roomInfo.id
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var creators: [String] {
|
||||
roomInfo.creators ?? []
|
||||
}
|
||||
@@ -24,6 +26,8 @@ nonisolated struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
roomInfo.displayName
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var rawName: String? {
|
||||
roomInfo.rawName
|
||||
}
|
||||
@@ -78,6 +82,8 @@ nonisolated struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
roomInfo.membership
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var inviter: RoomMemberProxyProtocol? {
|
||||
roomInfo.inviter.map(RoomMemberProxy.init)
|
||||
}
|
||||
@@ -90,6 +96,8 @@ nonisolated struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
Int(roomInfo.activeMembersCount)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var invitedMembersCount: Int {
|
||||
Int(roomInfo.invitedMembersCount)
|
||||
}
|
||||
@@ -98,14 +106,20 @@ nonisolated struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
Int(roomInfo.joinedMembersCount)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var highlightCount: Int {
|
||||
Int(roomInfo.highlightCount)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var notificationCount: Int {
|
||||
Int(roomInfo.notificationCount)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var cachedUserDefinedNotificationMode: RoomNotificationMode? {
|
||||
roomInfo.cachedUserDefinedNotificationMode
|
||||
}
|
||||
@@ -129,18 +143,26 @@ nonisolated struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
roomInfo.activeRoomCallParticipants
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var isMarkedUnread: Bool {
|
||||
roomInfo.isMarkedUnread
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var unreadMessagesCount: UInt {
|
||||
UInt(roomInfo.numUnreadMessages)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var unreadNotificationsCount: UInt {
|
||||
UInt(roomInfo.numUnreadNotifications)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
|
||||
var unreadMentionsCount: UInt {
|
||||
UInt(roomInfo.numUnreadMentions)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,10 @@ nonisolated protocol BaseRoomInfoProxyProtocol: Sendable {
|
||||
// sourcery: AutoMockable
|
||||
nonisolated protocol RoomInfoProxyProtocol: BaseRoomInfoProxyProtocol {
|
||||
var id: String { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var creators: [String] { get }
|
||||
var displayName: String? { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var rawName: String? { get }
|
||||
var topic: String? { get }
|
||||
/// The room's avatar URL. Use this for editing and favour ``avatar`` for display.
|
||||
@@ -43,20 +45,29 @@ nonisolated protocol RoomInfoProxyProtocol: BaseRoomInfoProxyProtocol {
|
||||
var canonicalAlias: String? { get }
|
||||
var alternativeAliases: [String] { get }
|
||||
var membership: Membership { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var inviter: RoomMemberProxyProtocol? { get }
|
||||
|
||||
var activeMembersCount: Int { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var invitedMembersCount: Int { get }
|
||||
var joinedMembersCount: Int { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var highlightCount: Int { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var notificationCount: Int { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var cachedUserDefinedNotificationMode: RoomNotificationMode? { get }
|
||||
var hasRoomCall: Bool { get }
|
||||
var activeRoomCallIntent: CallIntent? { get }
|
||||
var activeRoomCallParticipants: [String] { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var isMarkedUnread: Bool { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var unreadMessagesCount: UInt { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var unreadNotificationsCount: UInt { get }
|
||||
// periphery:ignore - might be useful to have
|
||||
var unreadMentionsCount: UInt { get }
|
||||
var fullyReadEventID: String? { get }
|
||||
var pinnedEventIDs: Set<String> { get }
|
||||
|
||||
@@ -56,6 +56,7 @@ final nonisolated class RoomMemberProxy: RoomMemberProxyProtocol {
|
||||
.init(rustPowerLevel: member.powerLevel)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
var isServiceMember: Bool {
|
||||
member.isServiceMember
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ nonisolated protocol RoomMemberProxyProtocol: AnyObject, Sendable {
|
||||
|
||||
var powerLevel: RoomPowerLevel { get }
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
var isServiceMember: Bool { get }
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@ nonisolated enum RoomPowerLevel: Hashable, Comparable {
|
||||
self = .value(value)
|
||||
}
|
||||
|
||||
init(value: Int64) {
|
||||
self = .value(Int(value))
|
||||
}
|
||||
|
||||
var rustPowerLevel: PowerLevel {
|
||||
switch self {
|
||||
case .infinite: .infinite
|
||||
|
||||
@@ -24,17 +24,6 @@ protocol RoomPowerLevelsProxyProtocol: Sendable {
|
||||
func canOwnUserPinOrUnpin() -> Bool
|
||||
func canOwnUserJoinCall() -> Bool
|
||||
func canOwnUserEditRolesAndPermissions() -> Bool
|
||||
|
||||
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError>
|
||||
func canUser(userID: String, sendStateEvent event: StateEventType) -> Result<Bool, RoomProxyError>
|
||||
func canUserInvite(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserRedactOther(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserRedactOwn(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserKick(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserBan(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserTriggerRoomNotification(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserPinOrUnpin(userID: String) -> Result<Bool, RoomProxyError>
|
||||
func canUserJoinCall(userID: String) -> Result<Bool, RoomProxyError>
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
@@ -70,94 +70,4 @@ nonisolated struct RoomPowerLevelsProxy: RoomPowerLevelsProxyProtocol {
|
||||
func canOwnUserEditRolesAndPermissions() -> Bool {
|
||||
powerLevels.canOwnUserSendState(stateEvent: .roomPowerLevels)
|
||||
}
|
||||
|
||||
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserSendMessage(userId: userID, message: messageType))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can send message with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUser(userID: String, sendStateEvent event: StateEventType) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserSendState(userId: userID, stateEvent: event))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can send \(event) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserInvite(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserInvite(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can invite with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserRedactOther(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserRedactOther(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can redact others with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserRedactOwn(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserRedactOwn(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can redact self with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserKick(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserKick(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can kick with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserBan(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserBan(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can ban with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserTriggerRoomNotification(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserTriggerRoomNotification(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can trigger room notification with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserPinOrUnpin(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserPinUnpin(userId: userID))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can pin or unnpin: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func canUserJoinCall(userID: String) -> Result<Bool, RoomProxyError> {
|
||||
do {
|
||||
return try .success(powerLevels.canUserSendState(userId: userID, stateEvent: .callMember))
|
||||
} catch {
|
||||
MXLog.error("Failed checking if the user can trigger room notification with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ enum RoomProxyError: Error {
|
||||
case invalidURL
|
||||
case invalidMedia
|
||||
case eventNotFound
|
||||
case missingTransactionID
|
||||
case failedCreatingPinnedTimeline
|
||||
case timelineError(TimelineProxyError)
|
||||
case liveLocationSessionIsNotActive
|
||||
@@ -57,22 +56,11 @@ protocol BannedRoomProxyProtocol: RoomProxyProtocol {
|
||||
func forgetRoom() async -> Result<Void, RoomProxyError>
|
||||
}
|
||||
|
||||
enum JoinedRoomProxyAction: Equatable {
|
||||
case roomInfoUpdate
|
||||
}
|
||||
|
||||
enum KnockRequestsState {
|
||||
case loading
|
||||
case loaded([KnockRequestProxyProtocol])
|
||||
}
|
||||
|
||||
struct RTCDeclinedEvent {
|
||||
/// The sender of the decline event
|
||||
let sender: String
|
||||
/// The rtc.notification event that is beeing declined
|
||||
let notificationEventID: String
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
var infoPublisher: CurrentValuePublisher<RoomInfoProxyProtocol, Never> { get }
|
||||
@@ -89,8 +77,6 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
|
||||
var predecessorRoom: PredecessorRoom? { get }
|
||||
|
||||
var successorRoom: SuccessorRoom? { get }
|
||||
|
||||
func subscribeForUpdates() async
|
||||
|
||||
func subscribeToRoomInfoUpdates()
|
||||
@@ -111,8 +97,6 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
|
||||
func enableEncryption() async -> Result<Void, RoomProxyError>
|
||||
|
||||
func redact(_ eventID: String) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func reportContent(_ eventID: String, reason: String?) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func reportRoom(reason: String) async -> Result<Void, RoomProxyError>
|
||||
@@ -135,8 +119,6 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
|
||||
func markAsRead(receiptType: ReceiptType) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, RoomProxyError>
|
||||
|
||||
/// https://spec.matrix.org/v1.9/client-server-api/#typing-notifications
|
||||
@discardableResult func sendTypingNotification(isTyping: Bool) async -> Result<Void, RoomProxyError>
|
||||
|
||||
@@ -167,10 +149,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
|
||||
// MARK: - Power Levels
|
||||
|
||||
func powerLevels() async -> Result<RoomPowerLevelsProxyProtocol?, RoomProxyError>
|
||||
func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result<Void, RoomProxyError>
|
||||
func resetPowerLevels() async -> Result<Void, RoomProxyError>
|
||||
func suggestedRole(for userID: String) async -> Result<RoomMemberRole, RoomProxyError>
|
||||
func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result<Void, RoomProxyError>
|
||||
|
||||
// MARK: - Moderation
|
||||
|
||||
@@ -106,6 +106,7 @@ nonisolated struct RoomEventStringBuilder {
|
||||
shouldPrefixSenderName: false)
|
||||
}
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
static func threadListEventStringBuilder(userID: String) -> Self {
|
||||
RoomEventStringBuilder(stateEventStringBuilder: .init(userID: userID),
|
||||
messageEventStringBuilder: .init(attributedStringBuilder: AttributedStringBuilder(cacheKey: "threadList", mentionBuilder: PlainMentionBuilder()),
|
||||
|
||||
@@ -21,13 +21,6 @@ nonisolated struct RoomSummary {
|
||||
default: false
|
||||
}
|
||||
}
|
||||
|
||||
var isKnock: Bool {
|
||||
switch self {
|
||||
case .knock: true
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum LastMessageState { case sending, failed }
|
||||
|
||||
@@ -26,7 +26,6 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
private var roomList: RoomListProtocol?
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var roomListServiceStateCancellable: AnyCancellable?
|
||||
private var listUpdatesSubscriptionResult: RoomListEntriesWithDynamicAdaptersResult?
|
||||
private var stateUpdatesTaskHandle: TaskHandle?
|
||||
|
||||
|
||||
@@ -13,19 +13,21 @@ class RoomThreadListProxy: RoomThreadListServiceProxyProtocol {
|
||||
private let threadListService: ThreadListServiceProtocol
|
||||
private let eventStringBuilder: RoomEventStringBuilder
|
||||
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var itemUpdatesHandle: TaskHandle?
|
||||
private let itemsSubject = CurrentValueSubject<[RoomThreadListItem], Never>([])
|
||||
var itemsPublisher: CurrentValuePublisher<[RoomThreadListItem], Never> {
|
||||
itemsSubject.asCurrentValuePublisher()
|
||||
}
|
||||
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var paginationStateHandle: TaskHandle?
|
||||
private let paginationStateSubject: CurrentValueSubject<RoomThreadListPaginationState, Never>
|
||||
var paginationStatePublisher: CurrentValuePublisher<RoomThreadListPaginationState, Never> {
|
||||
paginationStateSubject.asCurrentValuePublisher()
|
||||
}
|
||||
|
||||
init(threadListService: ThreadListServiceProtocol, eventStringBuilder: RoomEventStringBuilder, paginationToken: String? = nil) {
|
||||
init(threadListService: ThreadListServiceProtocol, eventStringBuilder: RoomEventStringBuilder) {
|
||||
self.threadListService = threadListService
|
||||
self.eventStringBuilder = eventStringBuilder
|
||||
|
||||
|
||||
Reference in New Issue
Block a user