Room's details edit screen (#956)

* Add RoomDetailsEditScreen template

* Add navigation to the edit screen

* Delete template code

* Start RoomDetailsEditScreen UI

* Manage power levels in RoomDetailsScreen

* Start RoomDetailsEditScreenViewModel logic

* Inject initial room state

* Add cancel action

* Expose set name/topic APIs in RoomProxy

* Refine RoomDetailsEditScreen UI

* Add save logic

* Add localisations

* Fix avatar image

* Update localisations

* Add “Add topic” button

* Add feature flag

* Add dismiss on save logic

* Reduce throttling

* Improve form logic

* Fix UT build errors

* Add media sheet

* Add media preprocessing

* Add LoadableEditableAvatarImage

* Add condition on delete image

* Add avatar save button logic

* Add remove avatar logic

* Cleanup

* Fix edit bug in DM

* Add upload avatar

* Add focus

* Add RoomDetailsViewModel UTs

* Fix button style

* Add UTs

* Add empty topic ui test

* Fix iPad sheet presentation

* Revert topic appearance in room’s details

* Address PR comments

* Add UI tests
This commit is contained in:
Alfonso Grillo
2023-05-26 15:47:12 +02:00
committed by GitHub
parent 524997438f
commit f2b7faa183
47 changed files with 1281 additions and 54 deletions
@@ -371,6 +371,27 @@ class RoomMemberProxyMock: RoomMemberProxyProtocol {
return unignoreUserReturnValue
}
}
//MARK: - canSendStateEvent
var canSendStateEventTypeCallsCount = 0
var canSendStateEventTypeCalled: Bool {
return canSendStateEventTypeCallsCount > 0
}
var canSendStateEventTypeReceivedType: StateEventType?
var canSendStateEventTypeReceivedInvocations: [StateEventType] = []
var canSendStateEventTypeReturnValue: Bool!
var canSendStateEventTypeClosure: ((StateEventType) -> Bool)?
func canSendStateEvent(type: StateEventType) -> Bool {
canSendStateEventTypeCallsCount += 1
canSendStateEventTypeReceivedType = type
canSendStateEventTypeReceivedInvocations.append(type)
if let canSendStateEventTypeClosure = canSendStateEventTypeClosure {
return canSendStateEventTypeClosure(type)
} else {
return canSendStateEventTypeReturnValue
}
}
}
class RoomProxyMock: RoomProxyProtocol {
var id: String {
@@ -419,11 +440,6 @@ class RoomProxyMock: RoomProxyProtocol {
set(value) { underlyingMembersPublisher = value }
}
var underlyingMembersPublisher: AnyPublisher<[RoomMemberProxyProtocol], Never>!
var updatesPublisher: AnyPublisher<TimelineDiff, Never> {
get { return underlyingUpdatesPublisher }
set(value) { underlyingUpdatesPublisher = value }
}
var underlyingUpdatesPublisher: AnyPublisher<TimelineDiff, Never>!
var invitedMembersCount: UInt {
get { return underlyingInvitedMembersCount }
set(value) { underlyingInvitedMembersCount = value }
@@ -439,6 +455,11 @@ class RoomProxyMock: RoomProxyProtocol {
set(value) { underlyingActiveMembersCount = value }
}
var underlyingActiveMembersCount: UInt!
var updatesPublisher: AnyPublisher<TimelineDiff, Never> {
get { return underlyingUpdatesPublisher }
set(value) { underlyingUpdatesPublisher = value }
}
var underlyingUpdatesPublisher: AnyPublisher<TimelineDiff, Never>!
//MARK: - loadAvatarURLForUserId
@@ -884,6 +905,86 @@ class RoomProxyMock: RoomProxyProtocol {
return inviteUserIDReturnValue
}
}
//MARK: - setName
var setNameCallsCount = 0
var setNameCalled: Bool {
return setNameCallsCount > 0
}
var setNameReceivedName: String?
var setNameReceivedInvocations: [String?] = []
var setNameReturnValue: Result<Void, RoomProxyError>!
var setNameClosure: ((String?) async -> Result<Void, RoomProxyError>)?
func setName(_ name: String?) async -> Result<Void, RoomProxyError> {
setNameCallsCount += 1
setNameReceivedName = name
setNameReceivedInvocations.append(name)
if let setNameClosure = setNameClosure {
return await setNameClosure(name)
} else {
return setNameReturnValue
}
}
//MARK: - setTopic
var setTopicCallsCount = 0
var setTopicCalled: Bool {
return setTopicCallsCount > 0
}
var setTopicReceivedTopic: String?
var setTopicReceivedInvocations: [String] = []
var setTopicReturnValue: Result<Void, RoomProxyError>!
var setTopicClosure: ((String) async -> Result<Void, RoomProxyError>)?
func setTopic(_ topic: String) async -> Result<Void, RoomProxyError> {
setTopicCallsCount += 1
setTopicReceivedTopic = topic
setTopicReceivedInvocations.append(topic)
if let setTopicClosure = setTopicClosure {
return await setTopicClosure(topic)
} else {
return setTopicReturnValue
}
}
//MARK: - removeAvatar
var removeAvatarCallsCount = 0
var removeAvatarCalled: Bool {
return removeAvatarCallsCount > 0
}
var removeAvatarReturnValue: Result<Void, RoomProxyError>!
var removeAvatarClosure: (() async -> Result<Void, RoomProxyError>)?
func removeAvatar() async -> Result<Void, RoomProxyError> {
removeAvatarCallsCount += 1
if let removeAvatarClosure = removeAvatarClosure {
return await removeAvatarClosure()
} else {
return removeAvatarReturnValue
}
}
//MARK: - uploadAvatar
var uploadAvatarMediaCallsCount = 0
var uploadAvatarMediaCalled: Bool {
return uploadAvatarMediaCallsCount > 0
}
var uploadAvatarMediaReceivedMedia: MediaInfo?
var uploadAvatarMediaReceivedInvocations: [MediaInfo] = []
var uploadAvatarMediaReturnValue: Result<Void, RoomProxyError>!
var uploadAvatarMediaClosure: ((MediaInfo) async -> Result<Void, RoomProxyError>)?
func uploadAvatar(media: MediaInfo) async -> Result<Void, RoomProxyError> {
uploadAvatarMediaCallsCount += 1
uploadAvatarMediaReceivedMedia = media
uploadAvatarMediaReceivedInvocations.append(media)
if let uploadAvatarMediaClosure = uploadAvatarMediaClosure {
return await uploadAvatarMediaClosure(media)
} else {
return uploadAvatarMediaReturnValue
}
}
}
class SessionVerificationControllerProxyMock: SessionVerificationControllerProxyProtocol {
var callbacks: PassthroughSubject<SessionVerificationControllerProxyCallback, Never> {