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

[UI/UX]Update ControlsView with CornerClipper #205

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
52 changes: 20 additions & 32 deletions DemoApp/Sources/Views/Controls/DemoControls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct AppControlsWithChat: View {
private var canOpenChat: Bool

private let size: CGFloat = 50
private let cornerRadius: CGFloat = 24

@ObservedObject var reactionsHelper = AppState.shared.reactionsHelper
@ObservedObject var viewModel: CallViewModel
Expand All @@ -28,41 +29,28 @@ struct AppControlsWithChat: View {
}

var body: some View {
VStack {
HStack(alignment: .center, spacing: 12) {
if let chatViewModel, chatViewModel.isChatEnabled {
ChatIconView(viewModel: chatViewModel)
}
VideoIconView(viewModel: viewModel)
MicrophoneIconView(viewModel: viewModel)
ToggleCameraIconView(viewModel: viewModel)
if !ProcessInfo.processInfo.isiOSAppOnMac {
BroadcastIconView(
viewModel: viewModel,
preferredExtension: "io.getstream.iOS.VideoDemoApp.ScreenSharing"
)
}
HangUpIconView(viewModel: viewModel)
HStack(alignment: .center, spacing: 12) {
if let chatViewModel, chatViewModel.isChatEnabled {
ChatIconView(viewModel: chatViewModel)
}
.frame(height: 85)
}
.frame(maxWidth: .infinity)
.background(
colors.callControlsBackground
.edgesIgnoringSafeArea(.all)
)
.overlay(
VStack {
colors.callControlsBackground
.frame(height: 30)
.cornerRadius(24)
Spacer()
VideoIconView(viewModel: viewModel)
MicrophoneIconView(viewModel: viewModel)
ToggleCameraIconView(viewModel: viewModel)
if !ProcessInfo.processInfo.isiOSAppOnMac {
BroadcastIconView(
viewModel: viewModel,
preferredExtension: "io.getstream.iOS.VideoDemoApp.ScreenSharing"
)
}
.offset(y: -15)
HangUpIconView(viewModel: viewModel)
}
.padding()
.clipCorners(
radius: cornerRadius,
corners: [.topLeft, .topRight],
backgroundColor: colors.callControlsBackground
)
.onReceive(viewModel.$call, perform: { call in
reactionsHelper.call = call
})
.onReceive(viewModel.$call) { reactionsHelper.call = $0 }
}
}

Expand Down
36 changes: 14 additions & 22 deletions Sources/StreamVideoSwiftUI/CallView/CallControlsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ public struct CallControlsView: View {
@Injected(\.streamVideo) var streamVideo

private let size: CGFloat = 50

private let cornerRadius: CGFloat = 24

@ObservedObject var viewModel: CallViewModel

@Injected(\.images) var images
Expand All @@ -23,37 +24,28 @@ public struct CallControlsView: View {
public var body: some View {
HStack(alignment: .top) {
Spacer()

VideoIconView(viewModel: viewModel)

Spacer()

MicrophoneIconView(viewModel: viewModel)

Spacer()

ToggleCameraIconView(viewModel: viewModel)

Spacer()

HangUpIconView(viewModel: viewModel)

Spacer()
}
.frame(maxWidth: .infinity)
.frame(height: 85)
.background(
colors.callControlsBackground
.edgesIgnoringSafeArea(.all)
)
.overlay(
VStack {
colors.callControlsBackground
.frame(height: 30)
.cornerRadius(24)
Spacer()
}
.offset(y: -15)
.padding()
.clipCorners(
radius: cornerRadius,
corners: [.topLeft, .topRight],
backgroundColor: colors.callControlsBackground
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/StreamVideoSwiftUI/CallView/CallView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public struct CallView<Factory: ViewFactory>: View {
}
}
}
.background(Color(colors.callBackground))
.background(Color(colors.callBackground).edgesIgnoringSafeArea(.all))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
UIApplication.shared.isIdleTimerDisabled = true
Expand Down
79 changes: 79 additions & 0 deletions Sources/StreamVideoSwiftUI/Utils/ClipCorners.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
//

import Foundation
import SwiftUI

/// `CornerClipper` is a ViewModifier that clips a SwiftUI view
/// to have rounded corners on specified sides.
public struct CornerClipper: ViewModifier {

/// The radius of the rounded corners.
public var radius: CGFloat

/// The corners that should be rounded.
public var corners: UIRectCorner

/// The background color that should extend below/above safeArea.
public var backgroundColor: Color

/// Modifies the provided content by clipping it to the shape with rounded corners.
/// - Parameter content: The content view to be modified.
public func body(content: Content) -> some View {
ZStack {
backgroundColor
.cornerRadius(radius)
.edgesIgnoringSafeArea(.all)

content
.clipShape(RoundedCorners(radius: radius, corners: corners))
.layoutPriority(1)
}
}
}

/// `RoundedCorners` is a Shape used to create a rounded cornered rectangle
/// on the specified sides using a given radius.
public struct RoundedCorners: Shape {

/// The radius of the rounded corners.
public var radius: CGFloat = .infinity

/// The corners to be rounded.
public var corners: UIRectCorner = .allCorners

/// Creates a path for the current shape.
/// - Parameter rect: The rectangle in which the path should be created.
public func path(in rect: CGRect) -> Path {
Path(
UIBezierPath(
roundedRect: rect,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius)
).cgPath
)
}
}

extension View {

/// Clips the corners of the current view.
/// - Parameters:
/// - radius: The radius for the rounded corners.
/// - corners: The corners that should be rounded.
/// - backgroundColor: The background color that should extend below/above safeArea.
public func clipCorners(
radius: CGFloat,
corners: UIRectCorner,
backgroundColor: Color = .clear
) -> some View {
modifier(
CornerClipper(
radius: radius,
corners: corners,
backgroundColor: backgroundColor
)
)
}
}
4 changes: 4 additions & 0 deletions StreamVideo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
4093861F2AA0A21800FF5AF4 /* MemoryLogViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4093861E2AA0A21800FF5AF4 /* MemoryLogViewer.swift */; };
409BFA402A9F79D2003341EF /* View+OptionalPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409BFA3F2A9F79D2003341EF /* View+OptionalPublisher.swift */; };
409BFA432A9F7BBB003341EF /* ReadableContentGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409BFA422A9F7BBB003341EF /* ReadableContentGuide.swift */; };
40AA2EE22AE0137E000DCA5C /* ClipCorners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40AA2EE02AE00179000DCA5C /* ClipCorners.swift */; };
40AB31262A49838000C270E1 /* EventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40AB31252A49838000C270E1 /* EventTests.swift */; };
40B499CA2AC1A5E100A53B60 /* OSLogDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B499C92AC1A5E100A53B60 /* OSLogDestination.swift */; };
40B499CC2AC1A90F00A53B60 /* DeeplinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B499CB2AC1A90F00A53B60 /* DeeplinkTests.swift */; };
Expand Down Expand Up @@ -920,6 +921,7 @@
4093861E2AA0A21800FF5AF4 /* MemoryLogViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryLogViewer.swift; sourceTree = "<group>"; };
409BFA3F2A9F79D2003341EF /* View+OptionalPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+OptionalPublisher.swift"; sourceTree = "<group>"; };
409BFA422A9F7BBB003341EF /* ReadableContentGuide.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableContentGuide.swift; sourceTree = "<group>"; };
40AA2EE02AE00179000DCA5C /* ClipCorners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipCorners.swift; sourceTree = "<group>"; };
40AB31252A49838000C270E1 /* EventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventTests.swift; sourceTree = "<group>"; };
40B499C92AC1A5E100A53B60 /* OSLogDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSLogDestination.swift; sourceTree = "<group>"; };
40B499CB2AC1A90F00A53B60 /* DeeplinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeeplinkTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2980,6 +2982,7 @@
84EBAA91288C135700BE3176 /* Utils */ = {
isa = PBXGroup;
children = (
40AA2EE02AE00179000DCA5C /* ClipCorners.swift */,
84EBAA92288C137E00BE3176 /* Modifiers.swift */,
84F3B0E3289174F60088751D /* ContainerHelpers.swift */,
8434C52C289AA41D0001490A /* ImageExtensions.swift */,
Expand Down Expand Up @@ -4268,6 +4271,7 @@
843697D228C7A25F00839D99 /* ParticipantsGridView.swift in Sources */,
840042CF2A70212D00917B30 /* ScreensharingControls.swift in Sources */,
8406269A2A37A5E2004B8748 /* CallEvents.swift in Sources */,
40AA2EE22AE0137E000DCA5C /* ClipCorners.swift in Sources */,
8415D3E3290BC882006E53CB /* Sounds.swift in Sources */,
84DCA2092A382B16000C3411 /* CallModels.swift in Sources */,
8442993C294232360037232A /* IncomingCallView_iOS13.swift in Sources */,
Expand Down
Loading