Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Custom Data Model injection feature #209

Merged
merged 22 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6408aa7
[Feature] Add an event for notifying when participants joined a call …
vhuseinova-msft May 2, 2022
63ce875
Merge branch 'develop/beta' of https://github.com/Azure/communication…
vhuseinova-msft May 3, 2022
57c02fe
[Feature] Add functionality for setting remote participant persona da…
vhuseinova-msft May 5, 2022
8a9ced0
Merge branch 'develop/beta' of https://github.com/Azure/communication…
vhuseinova-msft May 5, 2022
0caee9e
Merge branch 'develop/beta' of https://github.com/Azure/communication…
vhuseinova-msft May 6, 2022
a2dd7cc
Tests fix
vhuseinova-msft May 6, 2022
628c408
[Refactor] Update PersonaData argument name (#166)
JoshuaLai May 9, 2022
4743c88
[Feature] Display remote participants persona data in the grid view (…
vhuseinova-msft May 12, 2022
09caf07
Merge branch 'develop/beta' of github.com:Azure/communication-ui-libr…
JoshuaLai May 16, 2022
a74f23a
[Project] Resolve conflicts
JoshuaLai May 16, 2022
fcd37bc
[Project] Resolving project conflicts
JoshuaLai May 16, 2022
71e1b16
[Feature] Change how we set event handler (#174)
JoshuaLai May 17, 2022
f5b32a2
[DependancyContainer] fixing run time crash for avatar manager
JoshuaLai May 17, 2022
6dea57e
[Feature] Display participants view data in the participants list (#179)
vhuseinova-msft May 18, 2022
dab2ebe
Merge branch 'develop/beta' of github.com:Azure/communication-ui-libr…
JoshuaLai May 18, 2022
3d2167a
Merge branch 'develop/beta' of github.com:Azure/communication-ui-libr…
JoshuaLai May 18, 2022
2c90eca
Merge branch 'develop/beta' of https://github.com/Azure/communication…
vhuseinova-msft May 19, 2022
da84ee2
[Feature] Error handling for participants view data (#205)
vhuseinova-msft May 21, 2022
1c79190
[Project] Resolve conflicts in error manager
JoshuaLai May 24, 2022
ec46a8b
[Project] resolve project conflicts
JoshuaLai May 24, 2022
4566dc6
[Changelog] updating change log
JoshuaLai May 24, 2022
f3f5bbe
Merge branch 'develop/beta' into feature/customdatamodel
JoshuaLai May 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ struct RemoteParticipantAvatarHelper {
}
let renderDisplayName = selectedAvatarName.isEmpty ? nameIdValue : "\(selectedAvatarName) \(nameIdValue)"
let participantViewData = ParticipantViewData(avatar: avatarImage,
renderDisplayName: renderDisplayName)
callComposite.setRemoteParticipantViewData(for: identifier, participantViewData: participantViewData)
renderDisplayName: renderDisplayName)
callComposite.setRemoteParticipantViewData(for: identifier,
participantViewData: participantViewData)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,9 @@
FAC1FED027C98FC200D95845 /* BannerTextViewModelMocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC1FEC927C98FC200D95845 /* BannerTextViewModelMocking.swift */; };
FAC3128F27F24A8B00A4F1D0 /* IconButtonViewModelMocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC3128E27F24A8B00A4F1D0 /* IconButtonViewModelMocking.swift */; };
FAD845402819C129007DAFE1 /* RemoteParticipantsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD8453F2819C129007DAFE1 /* RemoteParticipantsManager.swift */; };
FAD845422819FC8E007DAFE1 /* CompositeRemoteParticipantsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD845412819FC8E007DAFE1 /* CompositeRemoteParticipantsManagerTests.swift */; };
FAD845422819FC8E007DAFE1 /* RemoteParticipantsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD845412819FC8E007DAFE1 /* RemoteParticipantsManagerTests.swift */; };
FAD845442819FFE6007DAFE1 /* CallingSDKEventsHandlerMocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD845432819FFE6007DAFE1 /* CallingSDKEventsHandlerMocking.swift */; };
FAFA427D28380F7500053EA7 /* AvatarViewManagerMocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFA427C28380F7500053EA7 /* AvatarViewManagerMocking.swift */; };
FB22A9D340197CA3DC74EEBB /* Pods_AzureCommunicationUICalling.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C580DBF67D8B5AEF7A801F90 /* Pods_AzureCommunicationUICalling.framework */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -504,8 +505,9 @@
FAC1FEC927C98FC200D95845 /* BannerTextViewModelMocking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BannerTextViewModelMocking.swift; sourceTree = "<group>"; };
FAC3128E27F24A8B00A4F1D0 /* IconButtonViewModelMocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconButtonViewModelMocking.swift; sourceTree = "<group>"; };
FAD8453F2819C129007DAFE1 /* RemoteParticipantsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteParticipantsManager.swift; sourceTree = "<group>"; };
FAD845412819FC8E007DAFE1 /* CompositeRemoteParticipantsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompositeRemoteParticipantsManagerTests.swift; sourceTree = "<group>"; };
FAD845412819FC8E007DAFE1 /* RemoteParticipantsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteParticipantsManagerTests.swift; sourceTree = "<group>"; };
FAD845432819FFE6007DAFE1 /* CallingSDKEventsHandlerMocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallingSDKEventsHandlerMocking.swift; sourceTree = "<group>"; };
FAFA427C28380F7500053EA7 /* AvatarViewManagerMocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AvatarViewManagerMocking.swift; path = Mocking/AvatarViewManagerMocking.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -743,7 +745,7 @@
children = (
1F4B0EF7269BD17600E87014 /* CompositeErrorManagerTests.swift */,
881D8F7527FCA8C4008EC897 /* AvatarManagerTests.swift */,
FAD845412819FC8E007DAFE1 /* CompositeRemoteParticipantsManagerTests.swift */,
FAD845412819FC8E007DAFE1 /* RemoteParticipantsManagerTests.swift */,
);
path = Manager;
sourceTree = "<group>";
Expand Down Expand Up @@ -1134,6 +1136,7 @@
FA62233627DAD9AF008B5466 /* AccessibilityProviderMocking.swift */,
50B390D027D82D7E0010A2ED /* LocalizationProviderMocking.swift */,
FAD845432819FFE6007DAFE1 /* CallingSDKEventsHandlerMocking.swift */,
FAFA427C28380F7500053EA7 /* AvatarViewManagerMocking.swift */,
);
name = Mocking;
sourceTree = "<group>";
Expand Down Expand Up @@ -1484,7 +1487,7 @@
503E361C26CC2D0900158CB4 /* CompositeViewModelFactoryTests.swift in Sources */,
503300FC2706763800289BB5 /* BannerViewModelTests.swift in Sources */,
A869A63F26546A2E003CC4F2 /* VideoViewManagerMocking.swift in Sources */,
FAD845422819FC8E007DAFE1 /* CompositeRemoteParticipantsManagerTests.swift in Sources */,
FAD845422819FC8E007DAFE1 /* RemoteParticipantsManagerTests.swift in Sources */,
A830C306264C3B6400766E3D /* AppStateReducerTests.swift in Sources */,
88BC24C12832D29D00818446 /* AvatarManagerTests.swift in Sources */,
FAC1FECF27C98FC200D95845 /* InfoHeaderViewModelMocking.swift in Sources */,
Expand Down Expand Up @@ -1542,6 +1545,7 @@
5A314750E50CDF6A6F4577E5 /* GroupCallOptionsTests.swift in Sources */,
FAC3128F27F24A8B00A4F1D0 /* IconButtonViewModelMocking.swift in Sources */,
FAC1FECD27C98FC200D95845 /* ParticipantGridCellViewModelMocking.swift in Sources */,
FAFA427D28380F7500053EA7 /* AvatarViewManagerMocking.swift in Sources */,
5A31429C377C213B53F19163 /* DependencyContainerTests.swift in Sources */,
1F09A10426BA472A00BACED7 /* ParticipantInfoModelBuilder.swift in Sources */,
FAC1FECE27C98FC200D95845 /* ParticipantGridViewModelMocking.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ public class CallComposite {
/// This is data is not sent up to ACS.
/// - Returns: The `Result` enum value with either a `Void` or an `Error`.
@discardableResult
public func setRemoteParticipantViewData(for identifier: CommunicationIdentifier,
participantViewData: ParticipantViewData) -> Result<Void, Error> {
public func setRemoteParticipantViewData(
for identifier: CommunicationIdentifier,
participantViewData: ParticipantViewData) -> Result<Void, CommunicationUIErrorEvent> {
guard let avatarManager = avatarViewManager else {
return .failure(CompositeError.callCompositeNotLaunched)
return .failure(CommunicationUIErrorEvent(code: CallCompositeErrorCode.remoteParticipantNotFound))
}

return avatarManager.setRemoteParticipantViewData(for: identifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public struct CallCompositeErrorCode {
/// Error when the input token is expired.
public static let tokenExpired: String = "tokenExpired"

/// Error when the remote participant is not found in the call.
public static let remoteParticipantNotFound: String = "RemoteParticipantNotFound"

/// Error when a participant is evicted from the call by another participant
static let callEvicted: String = "callEvicted"

Expand All @@ -24,7 +27,7 @@ public struct CallCompositeErrorCode {
}

/// The error thrown after Call Composite launching.
public struct CommunicationUIErrorEvent {
public struct CommunicationUIErrorEvent: Error {

/// The string representing the CallCompositeErrorCode.
public let code: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import AzureCommunicationCommon
import Combine

protocol AvatarViewManagerProtocol {
func setRemoteParticipantViewData(for identifier: CommunicationIdentifier,
participantViewData: ParticipantViewData) -> Result<Void, Error>
func setRemoteParticipantViewData(
for identifier: CommunicationIdentifier,
participantViewData: ParticipantViewData) -> Result<Void, CommunicationUIErrorEvent>
}

class AvatarViewManager: AvatarViewManagerProtocol, ObservableObject {
Expand Down Expand Up @@ -49,10 +50,14 @@ class AvatarViewManager: AvatarViewManagerProtocol, ObservableObject {
}
}

func setRemoteParticipantViewData(for identifier: CommunicationIdentifier,
participantViewData: ParticipantViewData) -> Result<Void, Error> {
guard let idStringValue = identifier.stringValue else {
return .failure(CompositeError.remoteParticipantNotFound)
func setRemoteParticipantViewData(
for identifier: CommunicationIdentifier,
participantViewData: ParticipantViewData) -> Result<Void, CommunicationUIErrorEvent> {
let participantsList = store.state.remoteParticipantsState.participantInfoList
guard let idStringValue = identifier.stringValue,
participantsList.contains(where: { $0.userIdentifier == idStringValue })
else {
return .failure(CommunicationUIErrorEvent(code: CallCompositeErrorCode.remoteParticipantNotFound))
}

if avatarStorage.value(forKey: idStringValue) != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class ErrorState: ReduxState, Equatable {
let error: CommunicationUIErrorEvent?
let errorCategory: ErrorCategory

public init(error: CommunicationUIErrorEvent? = nil,
errorCategory: ErrorCategory = .none) {
init(error: CommunicationUIErrorEvent? = nil,
errorCategory: ErrorCategory = .none) {
self.error = error
self.errorCategory = errorCategory
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class NavigationState: ReduxState, Equatable {

let status: NavigationStatus

public init(status: NavigationStatus = .setup) {
init(status: NavigationStatus = .setup) {
self.status = status
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Foundation

class Store<T: ReduxState>: ObservableObject {

@Published public var state: T
@Published var state: T

private var dispatchFunction: ActionDispatch!
private let reducer: Reducer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ enum CompositeError: String, LocalizedError, Equatable {

case invalidSDKWrapper = "InvalidSDKWrapper"
case invalidLocalVideoStream = "InvalidLocalVideoStream"
case callCompositeNotLaunched = "CallCompositeNotLaunched"
case remoteParticipantNotFound = "RemoteParticipantNotFound"

var localizedDescription: String { return NSLocalizedString(self.rawValue, comment: "") }
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,35 @@ class AvatarManagerTests: XCTestCase {
}

func test_avatarManager_setRemoteParticipantViewData_when_personeDataSet_then_participantViewDataDataUpdated() {
guard let mockImage = UIImage(named: "Icon/ic_fluent_call_end_24_filled",
in: Bundle(for: CallComposite.self),
compatibleWith: nil) else {
guard let mockImage = UIImage.make(withColor: .red) else {
XCTFail("UIImage does not exist")
return
}
let participant = ParticipantInfoModel(
displayName: "Participant 1",
isSpeaking: false,
isMuted: false,
isRemoteUser: true,
userIdentifier: "testUserIdentifier1",
recentSpeakingStamp: Date(),
screenShareVideoStreamModel: nil,
cameraVideoStreamModel: nil)
let remoteParticipantsState = RemoteParticipantsState(participantInfoList: [participant],
lastUpdateTimeStamp: Date())
mockStoreFactory.setState(AppState(remoteParticipantsState: remoteParticipantsState))
let sut = makeSUT()
let participantViewData = ParticipantViewData(avatar: mockImage)
let result = sut.setRemoteParticipantViewData(for: CommunicationUserIdentifier(participant.userIdentifier),
participantViewData: participantViewData)
guard case .success = result else {
XCTFail("Failed with result validation")
return
}
XCTAssertEqual(sut.avatarStorage.value(forKey: participant.userIdentifier)?.avatarImage!, mockImage)
}

func test_avatarManager_setRemoteParticipantViewData_when_avatarDataSet__and_participantNotOnCall_then_participantNotFoundErrorReturned() {
guard let mockImage = UIImage.make(withColor: .red) else {
XCTFail("UIImage does not exist")
return
}
Expand All @@ -39,11 +65,11 @@ class AvatarManagerTests: XCTestCase {
let id = UUID().uuidString
let result = sut.setRemoteParticipantViewData(for: CommunicationUserIdentifier(id),
participantViewData: participantViewData)
guard case .success = result else {
guard case .failure(let error) = result else {
XCTFail("Failed with result validation")
return
}
XCTAssertEqual(sut.avatarStorage.value(forKey: id)?.avatarImage!, mockImage)
XCTAssertEqual(error.code, CallCompositeErrorCode.remoteParticipantNotFound)
}
}

Expand Down
Loading