AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Presentation/SwiftUI/ViewComponents/Button/IconButton.swift (149 lines of code) (raw):

// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // import SwiftUI struct IconButton: View { @ObservedObject var viewModel: IconButtonViewModel private let buttonDisabledColor = Color(StyleProvider.color.disableColor) private var iconImageSize: CGFloat { switch viewModel.buttonType { case .dismissButton: return 16 default: return 24 } } var width: CGFloat { switch viewModel.buttonType { case .controlButton, .roundedRectButton: return 60 case .infoButton: return iconImageSize case .dismissButton: return 16 case .cameraSwitchButtonFull, .cameraSwitchButtonPip: return 36 } } var height: CGFloat { switch viewModel.buttonType { case .controlButton, .roundedRectButton: return 60 case .infoButton: return iconImageSize case .dismissButton: return 16 case .cameraSwitchButtonFull, .cameraSwitchButtonPip: return 36 } } var buttonBackgroundColor: Color { switch viewModel.buttonType { case .roundedRectButton: return Color(StyleProvider.color.hangup) case .controlButton, .infoButton, .dismissButton: return .clear case .cameraSwitchButtonFull, .cameraSwitchButtonPip: return Color(StyleProvider.color.surfaceLightColor) } } var buttonForegroundColor: Color { switch viewModel.buttonType { case .controlButton: return Color(StyleProvider.color.onSurfaceColor) case .dismissButton: return Color(StyleProvider.color.onBackground) default: return .white } } var tappableWidth: CGFloat { switch viewModel.buttonType { case .cameraSwitchButtonPip, .cameraSwitchButtonFull, .infoButton: return 44 default: return width } } var tappableHeight: CGFloat { switch viewModel.buttonType { case .cameraSwitchButtonPip, .cameraSwitchButtonFull, .infoButton: return 44 default: return height } } var shapeCornerRadius: CGFloat { switch viewModel.buttonType { case .cameraSwitchButtonPip, .cameraSwitchButtonFull: return 4 default: return 8 } } var roundedCorners: UIRectCorner { switch viewModel.buttonType { case .cameraSwitchButtonPip: return [.bottomLeft] default: return [.allCorners] } } var body: some View { if viewModel.isVisible { Group { Button(action: viewModel.action) { icon } .disabled(viewModel.isDisabled) .foregroundColor(viewModel.isDisabled ? buttonDisabledColor : buttonForegroundColor) .frame(width: width, height: height, alignment: .center) .background(buttonBackgroundColor) .clipShape(RoundedCornersShape(radius: shapeCornerRadius, corners: roundedCorners)) .accessibilityLabel(Text(viewModel.accessibilityLabel ?? "")) .accessibilityValue(Text(viewModel.accessibilityValue ?? "")) .accessibilityHint(Text(viewModel.accessibilityHint ?? "")) } .frame(width: tappableWidth, height: tappableHeight, alignment: .center) .contentShape(Rectangle()) .onTapGesture { // ignore action in case if button is disabled // .disabled(_) is not used because tap is passed to superview when it shouldn't guard !viewModel.isDisabled else { return } viewModel.action() } } } var icon: some View { var icon = Icon(size: iconImageSize) icon.contentShape(Rectangle()) if let uiImage = viewModel.icon { icon.uiImage = uiImage } if let iconName = viewModel.iconName { icon.name = iconName } return icon } } struct RoundedCornersShape: Shape { let radius: CGFloat let corners: UIRectCorner func path(in rect: CGRect) -> Path { let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) return Path(path.cgPath) } }