AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Presentation/SwiftUI/Calling/Grid/ParticipantGridLayoutView.swift (87 lines of code) (raw):

// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // import SwiftUI struct ParticipantGridLayoutView: View { var cellViewModels: [ParticipantGridCellViewModel] let rendererViewManager: RendererViewManager? let avatarViewManager: AvatarViewManagerProtocol let screenSize: ScreenSizeClassType let shouldUseVerticalStyleGrid: Bool let gridsMargin: CGFloat = 3 @Orientation var orientation: UIDeviceOrientation var body: some View { Group { if shouldUseVerticalStyleGrid { vGridLayout } else { let cellCount = cellViewModels.count let isPortrait = orientation.isPortrait let isiPadLanscape = orientation.isLandscape && screenSize == .ipadScreenSize let isiPadPortrait = isPortrait && (screenSize == .ipadScreenSize) if (cellCount == 5 && isiPadLanscape) || (cellCount == 8 && isiPadPortrait) || (cellCount == 7 && isiPadPortrait) || (cellCount == 3 && isiPadLanscape) { vGridLayout } else { hGridLayout } } } } func getChunkedCellViewModelArray() -> [[ParticipantGridCellViewModel]] { let cellCount = cellViewModels.count let vGridLayout = screenSize == .iphonePortraitScreenSize let isPortrait = orientation.isPortrait let isiPadLanscape = orientation.isLandscape && (screenSize == .ipadScreenSize) let isiPadPortrait = isPortrait && screenSize == .ipadScreenSize var screenBasedRowSize = 2 if screenSize != .ipadScreenSize { // iPhone layout is kept the same way as before screenBasedRowSize = cellViewModels.count == 2 ? 1 : 2 } else if cellCount <= 2 { // iPad layout for having 1 and 2 remote participants screenBasedRowSize = cellCount == 2 && isiPadPortrait ? 2 : 1 } else if cellCount % 2 == 0 { // iPad layout for having 4, 6 and 8 remote participants screenBasedRowSize = (isiPadLanscape && cellCount < 8) || (isPortrait && cellCount < 6) ? 2 : 3 } else if cellCount % 3 == 0 { // iPad layout for having 3 and 9 remote participants screenBasedRowSize = cellCount < 9 ? 2 : 3 } else { // iPad layout for having 5 and 7 remote participants screenBasedRowSize = cellCount < 5 ? 2 : 3 } return cellViewModels.chunkedAndReversed(into: screenBasedRowSize, vGridLayout: vGridLayout || isiPadLanscape) } /// Grid layout used in displying grid items on iPad and iPhone landscape mode var hGridLayout: some View { let chunkedArray = getChunkedCellViewModelArray() return HStack(spacing: gridsMargin) { ForEach(0..<chunkedArray.count, id: \.self) { index in VStack(spacing: gridsMargin) { getRowView(cellsViewModel: chunkedArray[index]) } } } .background(Color(StyleProvider.color.gridLayoutBackground)) .accessibilityElement(children: .contain) } /// Grid layout used in displying grid items on iPhone portrait mode var vGridLayout: some View { let chunkedArray = getChunkedCellViewModelArray() return VStack(spacing: gridsMargin) { ForEach(0..<chunkedArray.count, id: \.self) { index in HStack(spacing: gridsMargin) { getRowView(cellsViewModel: chunkedArray[index]) } } } .background(Color(StyleProvider.color.gridLayoutBackground)) .accessibilityElement(children: .contain) } func getRowView(cellsViewModel: [ParticipantGridCellViewModel]) -> some View { return ForEach(cellsViewModel) { vm in ParticipantGridCellView(viewModel: vm, rendererViewManager: rendererViewManager, avatarViewManager: avatarViewManager) .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(StyleProvider.color.surface)) .clipShape(RoundedRectangle(cornerRadius: 4)) .accessibilityElement(children: .contain) } } }